Ejemplo n.º 1
0
 private static int JumpOnCond(FuncState fs, expdesc e, int cond)
 {
     if (e.k == expkind.VRELOCABLE)
     {
         InstructionPtr ie = GetCode(fs, e);
         if (GET_OPCODE(ie) == OpCode.OP_NOT)
         {
             fs.pc--;        /* remove previous OpCode.OP_NOT */
             return(CondJump(fs, OpCode.OP_TEST, GETARG_B(ie), 0, (cond == 0) ? 1 : 0));
         }
         /* else go through */
     }
     Discharge2AnyReg(fs, e);
     FreeExp(fs, e);
     return(CondJump(fs, OpCode.OP_TESTSET, NO_REG, e.u.s.info, cond));
 }
Ejemplo n.º 2
0
 private static int jumponcond(FuncState fs, expdesc e, int cond)
 {
     if (e.k == expkind.VRELOCABLE)
     {
         InstructionPtr ie = getcode(fs, e);
         if (GET_OPCODE(ie) == OpCode.OP_NOT)
         {
             fs.pc--;        /* remove previous OpCode.OP_NOT */
             return(condjump(fs, OpCode.OP_TEST, GETARG_B(ie), 0, (cond == 0) ? 1 : 0));
         }
         /* else go through */
     }
     discharge2anyreg(fs, e);
     freeexp(fs, e);
     return(condjump(fs, OpCode.OP_TESTSET, NO_REG, e.u.info, cond));
 }
Ejemplo n.º 3
0
        private static void traceexec (lua_State L, InstructionPtr pc) {
            lu_byte mask = L.hookmask;
            InstructionPtr oldpc = InstructionPtr.Assign(L.savedpc);
            L.savedpc = InstructionPtr.Assign(pc);
            if (((mask & LUA_MASKCOUNT) != 0) && (L.hookcount == 0)) {
                resethookcount(L);
                luaD_callhook(L, LUA_HOOKCOUNT, -1);
            }
            if ((mask & LUA_MASKLINE) != 0) {
                Proto p = ci_func(L.ci).l.p;
                int npc = pcRel(pc, p);
                int newline = getline(p, npc);
                /* call linehook when enter a new function, when jump back (loop),
			   or when enter a new line */
                if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))
                    luaD_callhook(L, LUA_HOOKLINE, newline);
            }
        }
Ejemplo n.º 4
0
 /*
 ** Fix an expression to return the number of results 'nresults'.
 ** Either 'e' is a multi-ret expression (function call or vararg)
 ** or 'nresults' is LUA_MULTRET (as any expression can satisfy that).
 */
 public static void luaK_setreturns(FuncState fs, expdesc e, int nresults)
 {
     if (e.k == expkind.VCALL)          /* expression is an open function call? */
     {
         SETARG_C(getinstruction(fs, e), nresults + 1);
     }
     else if (e.k == expkind.VVARARG)
     {
         InstructionPtr pc = getinstruction(fs, e);
         SETARG_B(pc, nresults + 1);
         SETARG_A(pc, fs.freereg);
         luaK_reserveregs(fs, 1);
     }
     else
     {
         lua_assert(nresults == LUA_MULTRET);
     }
 }
Ejemplo n.º 5
0
 public static void arith_op(lua_State L, op_delegate op, TMS tm, StkId base_, Instruction i, TValue[] k, StkId ra, InstructionPtr pc)
 {
     TValue rb = RKB(L, base_, i, k);
         TValue rc = RKC(L, base_, i, k);
         if (ttisnumber(rb) && ttisnumber(rc))
         {
             lua_Number nb = nvalue(rb), nc = nvalue(rc);
             setnvalue(ra, op(nb, nc));
         }
         else
         {
             //Protect(
             L.savedpc = InstructionPtr.Assign(pc);
             Arith(L, ra, rb, rc, tm);
             base_ = L.base_;
             //);
         }
 }
Ejemplo n.º 6
0
		private static void traceexec (LuaState L, InstructionPtr pc) {
		  lu_byte mask = L.hookmask;
		  InstructionPtr oldpc = InstructionPtr.Assign(L.savedpc);
		  L.savedpc = InstructionPtr.Assign(pc);
		  if (((mask & LUA_MASKCOUNT) != 0) && (L.hookcount == 0)) {
			ResetHookCount(L);
			LuaDCallHook(L, LUA_HOOKCOUNT, -1);
		  }
		  if ((mask & LUA_MASKLINE) != 0) {
			Proto p = CIFunc(L.ci).l.p;
			int npc = PCRel(pc, p);
			int newline = GetLine(p, npc);
			/* call linehook when enter a new function, when jump back (loop),
			   or when enter a new line */
			if (npc == 0 || pc <= oldpc || newline != GetLine(p, PCRel(oldpc, p)))
			  LuaDCallHook(L, LUA_HOOKLINE, newline);
		  }
		}
Ejemplo n.º 7
0
        public static void luaG_traceexec(lua_State L)
        {
            CallInfo ci        = L.ci;
            lu_byte  mask      = L.hookmask;
            int      counthook = ((mask & LUA_MASKCOUNT) != 0 && L.hookcount == 0) ? 1 : 0;

            if (counthook != 0)
            {
                resethookcount(L);                                 /* reset count */
            }
            if ((ci.callstatus & CIST_HOOKYIELD) != 0)             /* called hook last time? */
            {
                ci.callstatus &= (byte)((~CIST_HOOKYIELD) & 0xff); /* erase mark */
                return;                                            /* do not call hook again (VM yielded, so it did not move) */
            }
            if (counthook != 0)
            {
                luaD_hook(L, LUA_HOOKCOUNT, -1);      /* call count hook */
            }
            if ((mask & LUA_MASKLINE) != 0)
            {
                Proto p       = ci_func(ci).p;
                int   npc     = pcRel(ci.u.l.savedpc, p);
                int   newline = getfuncline(p, npc);
                if (npc == 0 ||                                   /* call linehook when enter a new function, */
                    ci.u.l.savedpc <= L.oldpc ||                  /* when jump back (loop), or when */
                    newline != getfuncline(p, pcRel(L.oldpc, p))) /* enter a new line */
                {
                    luaD_hook(L, LUA_HOOKLINE, newline);          /* call line hook */
                }
            }
            L.oldpc = ci.u.l.savedpc;
            if (L.status == LUA_YIELD)          /* did hook yield? */
            {
                if (counthook != 0)
                {
                    L.hookcount = 1;                    /* undo decrement to zero */
                }
                InstructionPtr.dec(ref ci.u.l.savedpc); /* undo increment (resume will increment it again) */
                ci.callstatus |= CIST_HOOKYIELD;        /* mark that it yielded */
                ci.func        = L.top - 1;             /* protect stack below results */
                luaD_throw(L, LUA_YIELD);
            }
        }
Ejemplo n.º 8
0
        public static void arith_op(lua_State L, op_delegate op, TMS tm, StkId base_, Instruction i, TValue[] k, StkId ra, InstructionPtr pc)
        {
            TValue rb = RKB(L, base_, i, k);
            TValue rc = RKC(L, base_, i, k);

            if (ttisnumber(rb) && ttisnumber(rc))
            {
                lua_Number nb = nvalue(rb), nc = nvalue(rc);
                setnvalue(ra, op(nb, nc));
            }
            else
            {
                //Protect(
                L.savedpc = InstructionPtr.Assign(pc);
                Arith(L, ra, rb, rc, tm);
                base_ = L.base_;
                //);
            }
        }
Ejemplo n.º 9
0
        private static int patchtestreg(FuncState fs, int node, int reg)
        {
            InstructionPtr i = getjumpcontrol(fs, node);

            if (GET_OPCODE(i[0]) != OpCode.OP_TESTSET)
            {
                return(0);         /* cannot patch other instructions */
            }
            if (reg != NO_REG && reg != GETARG_B(i[0]))
            {
                SETARG_A(i, reg);
            }
            else        /* no register to put value or register already has the value */
            {
                i[0] = (uint)CREATE_ABC(OpCode.OP_TEST, GETARG_B(i[0]), 0, GETARG_C(i[0]));
            }

            return(1);
        }
Ejemplo n.º 10
0
        public static void luaK_nil(FuncState fs, int from, int n)
        {
            InstructionPtr previous;

            if (fs.pc > fs.lasttarget)          /* no jumps to current position? */
            {
                previous = new InstructionPtr(fs.f.code, fs.pc - 1);
                if (GET_OPCODE(previous) == OpCode.OP_LOADNIL)
                {
                    int pfrom = GETARG_A(previous);
                    int pto   = GETARG_B(previous);
                    if (pfrom <= from && from <= pto + 1)        /* can connect both? */
                    {
                        if (from + n - 1 > pto)
                        {
                            SETARG_B(previous, from + n - 1);
                        }
                        return;
                    }
                }
            }
            luaK_codeABC(fs, OpCode.OP_LOADNIL, from, from + n - 1, 0);        /* else no optimization */
        }
Ejemplo n.º 11
0
        public static int luaD_pcall(lua_State L, Pfunc func, object u,
                                     ptrdiff_t old_top, ptrdiff_t ef)
        {
            int       status;
            ptrdiff_t old_ci         = saveci(L, L.ci);
            lu_byte   old_allowhooks = L.allowhook;
            ptrdiff_t old_errfunc    = L.errfunc;

            L.errfunc = ef;
            status    = luaD_rawrunprotected(L, func, u);
            if (status != LUA_OK)          /* an error occurred? */
            {
                StkId oldtop = restorestack(L, old_top);
                luaF_close(L, oldtop);          /* close possible pending closures */
                luaD_seterrorobj(L, status, oldtop);
                L.ci    = restoreci(L, old_ci);
                L.base_ = L.ci.base_;
                InstructionPtr.Assign(L.ci.savedpc, ref L.savedpc);
                L.allowhook = old_allowhooks;
                restore_stack_limit(L);
            }
            L.errfunc = old_errfunc;
            return(status);
        }
Ejemplo n.º 12
0
 internal static void SETARG_sBx(InstructionPtr i, int b)
 {
     SETARG_Bx(i, b + MAXARG_sBx);
 }
Ejemplo n.º 13
0
 public static OpCode GET_OPCODE(InstructionPtr i)
 {
     return(GET_OPCODE(i[0]));
 }
Ejemplo n.º 14
0
 public static void dojump(lua_State L, InstructionPtr pc, int i)
 {
     pc.pc += i;
 }
Ejemplo n.º 15
0
 public static void setarg(InstructionPtr i, int v, int pos, int size)
 {
     //FIXME: changed here
     i[0] = (Instruction)((i[0] & MASK0(size, pos)) |
                          ((((int)v) << pos) & MASK1(size, pos)));
 }
Ejemplo n.º 16
0
        public static int luaD_precall(lua_State L, StkId func, int nresults)
        {
            LClosure  cl;
            ptrdiff_t funcr;

            if (!ttisfunction(func))       /* `func' is not a function? */
            {
                func = tryfuncTM(L, func); /* check the `function' tag method */
            }
            funcr = savestack(L, func);
            cl    = clvalue(func).l;
            InstructionPtr.Assign(L.savedpc, ref L.ci.savedpc);
            if (cl.isC == 0)        /* Lua function? prepare its call */
            {
                CallInfo ci;
                StkId    st, base_;
                Proto    p = cl.p;
                luaD_checkstack(L, p.maxstacksize);
                func = restorestack(L, funcr);
                if (p.is_vararg == 0)            /* no varargs? */
                {
                    base_ = L.stack[func + 1];
                    if (L.top > base_ + p.numparams)
                    {
                        L.top = base_ + p.numparams;
                    }
                }
                else            /* vararg function */
                {
                    int nargs = L.top - func - 1;
                    base_ = adjust_varargs(L, p, nargs);
                    func  = restorestack(L, funcr); /* previous call may change the stack */
                }
                ci      = inc_ci(L);                /* now `enter' new function */
                ci.func = func;
                L.base_ = ci.base_ = base_;
                ci.top  = L.base_ + p.maxstacksize;
                lua_assert(ci.top <= L.stack_last);
                L.savedpc    = new InstructionPtr(p.code, 0);       /* starting point */
                ci.tailcalls = 0;
                ci.nresults  = nresults;
                for (st = L.top; st < ci.top; StkId.inc(ref st))
                {
                    setnilvalue(st);
                }
                L.top = ci.top;
                if ((L.hookmask & LUA_MASKCALL) != 0)
                {
                    InstructionPtr.inc(ref L.savedpc);        /* hooks assume 'pc' is already incremented */
                    luaD_callhook(L, LUA_HOOKCALL, -1);
                    InstructionPtr.dec(ref L.savedpc);        /* correct 'pc' */
                }
                return(PCRLUA);
            }
            else          /* if is a C function, call it */
            {
                CallInfo ci;
                int      n;
                luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
                ci      = inc_ci(L);              /* now `enter' new function */
                ci.func = restorestack(L, funcr);
                L.base_ = ci.base_ = ci.func + 1;
                ci.top  = L.top + LUA_MINSTACK;
                lua_assert(ci.top <= L.stack_last);
                ci.nresults = nresults;
                if ((L.hookmask & LUA_MASKCALL) != 0)
                {
                    luaD_callhook(L, LUA_HOOKCALL, -1);
                }
                lua_unlock(L);
                n = curr_func(L).c.f(L); /* do the actual call */
                lua_lock(L);
                if (n < 0)               /* yielding? */
                {
                    return(PCRYIELD);
                }
                else
                {
                    luaD_poscall(L, L.top - n);
                    return(PCRC);
                }
            }
        }
Ejemplo n.º 17
0
        public static void luaV_execute(lua_State L)
        {
            CallInfo ci = L.ci;
            LClosure cl = clvalue(ci.func).l;

            TValue[] k     = cl.p.k;
            StkId    base_ = ci.u.l.base_;

            lua_assert(isLua(ci));
            /* main loop of interpreter */
            for (;;)
            {
                Instruction i = ci.u.l.savedpc[0]; InstructionPtr.inc(ref ci.u.l.savedpc);         //FIXME:++
                StkId       ra;
                if (((L.hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) != 0) &&
                    (((--L.hookcount) == 0) || ((L.hookmask & LUA_MASKLINE) != 0)))
                {
                    traceexec(L);
                    if (L.status == LUA_YIELD)                  /* did hook yield? */
                    {
                        InstructionPtr.dec(ref ci.u.l.savedpc); /* undo increment */
                        luaD_throw(L, LUA_YIELD);
                    }
                    base_ = ci.u.l.base_;
                }
                /* warning!! several calls may realloc the stack and invalidate `ra' */
                ra = RA(L, base_, i);
                lua_assert(base_ == ci.u.l.base_);
                lua_assert(base_ <= L.top && ((L.top - L.stack) <= L.stacksize));
                //Dump(L.ci.u.l.savedpc.pc, i);	//FIXME:added, only for debugging
                switch (GET_OPCODE(i))
                {
                case OpCode.OP_MOVE: {
                    setobjs2s(L, ra, RB(L, base_, i));
                    continue;
                }

                case OpCode.OP_LOADK: {
                    setobj2s(L, ra, KBx(L, i, k));
                    continue;
                }

                case OpCode.OP_LOADBOOL: {
                    setbvalue(ra, GETARG_B(i));
                    if (GETARG_C(i) != 0)
                    {
                        InstructionPtr.inc(ref ci.u.l.savedpc);                                /* skip next instruction (if C) */
                    }
                    continue;
                }

                case OpCode.OP_LOADNIL: {
                    TValue rb = RB(L, base_, i);
                    do
                    {
                        setnilvalue(StkId.dec(ref rb));
                    } while (rb >= ra);
                    continue;
                }

                case OpCode.OP_GETUPVAL: {
                    int b = GETARG_B(i);
                    setobj2s(L, ra, cl.upvals[b].v);
                    continue;
                }

                case OpCode.OP_GETGLOBAL: {
                    TValue g  = new TValue();
                    TValue rb = KBx(L, i, k);
                    sethvalue(L, g, cl.env);
                    lua_assert(ttisstring(rb));
                    //Protect(
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:
                    luaV_gettable(L, g, rb, ra);
                    base_ = ci.u.l.base_;
                    //);
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:???
                    continue;
                }

                case OpCode.OP_GETTABLE: {
                    //Protect(
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:
                    luaV_gettable(L, RB(L, base_, i), RKC(L, base_, i, k), ra);
                    base_ = ci.u.l.base_;
                    //);
                    //L.savedpc = InstructionPtr.Assign(pc);//FIXME:???
                    continue;
                }

                case OpCode.OP_SETGLOBAL: {
                    TValue g = new TValue();
                    sethvalue(L, g, cl.env);
                    lua_assert(ttisstring(KBx(L, i, k)));
                    //Protect(
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:
                    luaV_settable(L, g, KBx(L, i, k), ra);
                    base_ = ci.u.l.base_;
                    //);
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:???
                    continue;
                }

                case OpCode.OP_SETUPVAL: {
                    UpVal uv = cl.upvals[GETARG_B(i)];
                    setobj(L, uv.v, ra);
                    luaC_barrier(L, uv, ra);
                    continue;
                }

                case OpCode.OP_SETTABLE: {
                    //Protect(
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:
                    luaV_settable(L, ra, RKB(L, base_, i, k), RKC(L, base_, i, k));
                    base_ = ci.u.l.base_;
                    //);
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:???
                    continue;
                }

                case OpCode.OP_NEWTABLE: {
                    int   b = GETARG_B(i);
                    int   c = GETARG_C(i);
                    Table t = luaH_new(L);
                    sethvalue(L, ra, t);
                    if (b != 0 || c != 0)
                    {
                        luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));
                    }
                    //Protect(
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:
                    luaC_checkGC(L);
                    base_ = ci.u.l.base_;
                    //);
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:???
                    continue;
                }

                case OpCode.OP_SELF: {
                    StkId rb = RB(L, base_, i);
                    setobjs2s(L, ra + 1, rb);
                    //Protect(
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:
                    luaV_gettable(L, rb, RKC(L, base_, i, k), ra);
                    base_ = ci.u.l.base_;
                    //);
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:???
                    continue;
                }

                case OpCode.OP_ADD: {
                    arith_op(L, luai_numadd, TMS.TM_ADD, base_, i, k, ra, ci);
                    continue;
                }

                case OpCode.OP_SUB: {
                    arith_op(L, luai_numsub, TMS.TM_SUB, base_, i, k, ra, ci);
                    continue;
                }

                case OpCode.OP_MUL: {
                    arith_op(L, luai_nummul, TMS.TM_MUL, base_, i, k, ra, ci);
                    continue;
                }

                case OpCode.OP_DIV: {
                    arith_op(L, luai_numdiv, TMS.TM_DIV, base_, i, k, ra, ci);
                    continue;
                }

                case OpCode.OP_MOD: {
                    arith_op(L, luai_nummod, TMS.TM_MOD, base_, i, k, ra, ci);
                    continue;
                }

                case OpCode.OP_POW: {
                    arith_op(L, luai_numpow, TMS.TM_POW, base_, i, k, ra, ci);
                    continue;
                }

                case OpCode.OP_UNM: {
                    TValue rb = RB(L, base_, i);
                    if (ttisnumber(rb))
                    {
                        lua_Number nb = nvalue(rb);
                        setnvalue(ra, luai_numunm(L, nb));
                    }
                    else
                    {
                        //Protect(
                        //L.savedpc = InstructionPtr.Assign(pc); //FIXME:
                        luaV_arith(L, ra, rb, rb, TMS.TM_UNM);
                        base_ = ci.u.l.base_;
                        //);
                        //L.savedpc = InstructionPtr.Assign(pc);//FIXME:???
                    }
                    continue;
                }

                case OpCode.OP_NOT: {
                    int res = l_isfalse(RB(L, base_, i)) == 0 ? 0 : 1;              /* next assignment may change this value */
                    setbvalue(ra, res);
                    continue;
                }

                case OpCode.OP_LEN: {
                    //Protect(
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:
                    objlen(L, ra, RB(L, base_, i));
                    base_ = ci.u.l.base_;               //FIXME:???
                    //)
                    continue;
                }

                case OpCode.OP_CONCAT: {
                    int b = GETARG_B(i);
                    int c = GETARG_C(i);
                    L.top = base_ + c + 1;              /* mark the end of concat operands */
                    //Protect(
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:
                    luaV_concat(L, c - b + 1); luaC_checkGC(L);
                    base_ = ci.u.l.base_;
                    //);
                    L.top = ci.top;              /* restore top */
                    setobjs2s(L, RA(L, base_, i), base_ + b);
                    continue;
                }

                case OpCode.OP_JMP: {
                    dojump(GETARG_sBx(i), ci, L);
                    continue;
                }

                case OpCode.OP_EQ: {
                    TValue rb = RKB(L, base_, i, k);
                    TValue rc = RKC(L, base_, i, k);
                    //Protect(
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:
                    if (equalobj(L, rb, rc) == GETARG_A(i))
                    {
                        dojump(GETARG_sBx(ci.u.l.savedpc[0]), ci, L);
                    }
                    base_ = ci.u.l.base_;
                    //);
                    InstructionPtr.inc(ref ci.u.l.savedpc);
                    continue;
                }

                case OpCode.OP_LT: {
                    //Protect(
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:
                    if (luaV_lessthan(L, RKB(L, base_, i, k), RKC(L, base_, i, k)) == GETARG_A(i))
                    {
                        dojump(GETARG_sBx(ci.u.l.savedpc[0]), ci, L);
                    }
                    base_ = ci.u.l.base_;
                    //);
                    InstructionPtr.inc(ref ci.u.l.savedpc);
                    continue;
                }

                case OpCode.OP_LE: {
                    //Protect(
                    //L.savedpc = InstructionPtr.Assign(pc); //FIXME:
                    if (luaV_lessequal(L, RKB(L, base_, i, k), RKC(L, base_, i, k)) == GETARG_A(i))
                    {
                        dojump(GETARG_sBx(ci.u.l.savedpc[0]), ci, L);
                    }
                    base_ = ci.u.l.base_;
                    //);
                    InstructionPtr.inc(ref ci.u.l.savedpc);
                    continue;
                }

                case OpCode.OP_TEST: {
                    if (GETARG_C(i) != 0 ? l_isfalse(ra) == 0 : l_isfalse(ra) != 0)
                    {
                        dojump(GETARG_sBx(ci.u.l.savedpc[0]), ci, L);
                    }
                    InstructionPtr.inc(ref ci.u.l.savedpc);
                    continue;
                }

                case OpCode.OP_TESTSET: {
                    TValue rb = RB(L, base_, i);
                    if (GETARG_C(i) != 0 ? l_isfalse(rb) == 0 : l_isfalse(rb) != 0)
                    {
                        setobjs2s(L, ra, rb);
                        dojump(GETARG_sBx(ci.u.l.savedpc[0]), ci, L);
                    }
                    InstructionPtr.inc(ref ci.u.l.savedpc);
                    continue;
                }

                case OpCode.OP_CALL: {
                    int b        = GETARG_B(i);
                    int nresults = GETARG_C(i) - 1;
                    if (b != 0)
                    {
                        L.top = ra + b;                     /* else previous instruction set top */
                    }
                    if (luaD_precall(L, ra, nresults) != 0) /* C function? */
                    {
                        if (nresults >= 0)
                        {
                            L.top = ci.top;                   /* adjust results */
                        }
                        base_ = ci.u.l.base_;
                        continue;
                    }
                    else        /* Lua function */
                    {
                        ci             = L.ci;
                        ci.callstatus |= CIST_REENTRY;
                        break;    /* restart luaV_execute over new Lua function */
                    }
                }

                case OpCode.OP_TAILCALL: {
                    int b = GETARG_B(i);
                    if (b != 0)
                    {
                        L.top = ra + b;                      /* else previous instruction set top */
                    }
                    lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
                    if (luaD_precall(L, ra, LUA_MULTRET) != 0)        /* C function? */
                    {
                        base_ = ci.u.l.base_;
                        continue;
                    }
                    else
                    {
                        /* tail call: put called frame (n) in place of caller one (o) */
                        CallInfo nci   = L.ci;         /* called frame */
                        CallInfo oci   = nci.previous; /* caller frame */
                        StkId    nfunc = nci.func;     /* called function index */
                        StkId    ofunc = oci.func;
                        int      aux;
                        if (cl.p.sizep > 0)
                        {
                            luaF_close(L, oci.u.l.base_);
                        }
                        oci.u.l.base_ = ofunc + (nci.u.l.base_ - nfunc);
                        for (aux = 0; nfunc + aux < L.top; aux++)    /* move frame down */
                        {
                            setobjs2s(L, ofunc + aux, nfunc + aux);
                        }
                        oci.top = L.top = ofunc + aux;      /* correct top */
                        lua_assert(L.top == oci.u.l.base_ + clvalue(ofunc).l.p.maxstacksize);
                        oci.u.l.savedpc = nci.u.l.savedpc;
                        oci.u.l.tailcalls++; /* one more call lost */
                        ci = L.ci = oci;     /* remove new frame */
                        break;               /* restart luaV_execute over new Lua function */
                    }
                }

                case OpCode.OP_RETURN: {
                    int b = GETARG_B(i);
                    if (b != 0)
                    {
                        L.top = ra + b - 1;
                    }
                    if (cl.p.sizep > 0)
                    {
                        luaF_close(L, base_);
                    }
                    b = luaD_poscall(L, ra);
                    if ((ci.callstatus & CIST_REENTRY) == 0) /* 'ci' still the called one */
                    {
                        return;                              /* external invocation: return */
                    }
                    else                                     /* invocation via reentry: continue execution */
                    {
                        ci = L.ci;
                        if (b != 0)
                        {
                            L.top = ci.top;
                        }
                        lua_assert(isLua(ci));
                        lua_assert(GET_OPCODE(ci.u.l.savedpc[-1]) == OpCode.OP_CALL);
                        break;    /* restart luaV_execute over new Lua function */
                    }
                }

                case OpCode.OP_FORLOOP: {
                    lua_Number step  = nvalue(ra + 2);
                    lua_Number idx   = luai_numadd(L, nvalue(ra), step);           /* increment index */
                    lua_Number limit = nvalue(ra + 1);
                    if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit)
                                                                                : luai_numle(L, limit, idx))
                    {
                        dojump(GETARG_sBx(i), ci, L);  /* jump back */
                        setnvalue(ra, idx);            /* update internal index... */
                        setnvalue(ra + 3, idx);        /* ...and external index */
                    }
                    continue;
                }

                case OpCode.OP_FORPREP: {
                    TValue init   = ra;
                    TValue plimit = ra + 1;
                    TValue pstep  = ra + 2;
                    if (tonumber(ref init, ra) == 0)
                    {
                        luaG_runerror(L, LUA_QL("for") + " initial value must be a number");
                    }
                    else if (tonumber(ref plimit, ra + 1) == 0)
                    {
                        luaG_runerror(L, LUA_QL("for") + " limit must be a number");
                    }
                    else if (tonumber(ref pstep, ra + 2) == 0)
                    {
                        luaG_runerror(L, LUA_QL("for") + " step must be a number");
                    }
                    setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep)));
                    dojump(GETARG_sBx(i), ci, L);
                    continue;
                }

                case OpCode.OP_TFORCALL: {
                    StkId cb = ra + 3;              /* call base */
                    setobjs2s(L, cb + 2, ra + 2);
                    setobjs2s(L, cb + 1, ra + 1);
                    setobjs2s(L, cb, ra);
                    L.top = cb + 3;            /* func. + 2 args (state and index) */
                    //Protect(
                    //L.savedpc = InstructionPtr.Assign(pc);//FIXME:
                    luaD_call(L, cb, GETARG_C(i), 1);
                    base_ = ci.u.l.base_;
                    //);
                    L.top = ci.top;
                    i     = ci.u.l.savedpc[0]; InstructionPtr.inc(ref ci.u.l.savedpc); /* go to next instruction */  //FIXME:++
                    ra    = RA(L, base_, i);
                    lua_assert(GET_OPCODE(i) == OpCode.OP_TFORLOOP);
                    /* go through */
                    goto case OpCode.OP_TFORLOOP;             //FIXME:added
                }

                case OpCode.OP_TFORLOOP: {
                    if (!ttisnil(ra + 1))             /* continue loop? */
                    {
                        setobjs2s(L, ra, ra + 1);     /* save control variable */
                        dojump(GETARG_sBx(i), ci, L); /* jump back */
                    }
                    continue;
                }

                case OpCode.OP_SETLIST: {
                    int   n = GETARG_B(i);
                    int   c = GETARG_C(i);
                    int   last;
                    Table h;
                    if (n == 0)
                    {
                        n = cast_int(L.top - ra) - 1;
                    }
                    if (c == 0)
                    {
                        lua_assert(GET_OPCODE(ci.u.l.savedpc[0]) == OpCode.OP_EXTRAARG);
                        c = GETARG_Ax(ci.u.l.savedpc[0]); InstructionPtr.inc(ref ci.u.l.savedpc); //FIXME:++
                    }
                    h    = hvalue(ra);
                    last = ((c - 1) * LFIELDS_PER_FLUSH) + n;
                    if (last > h.sizearray)              /* needs more space? */
                    {
                        luaH_resizearray(L, h, last);    /* pre-alloc it at once */
                    }
                    for (; n > 0; n--)
                    {
                        TValue val = ra + n;
                        setobj2t(L, luaH_setnum(L, h, last--), val);
                        luaC_barriert(L, h, val);
                    }
                    L.top = ci.top; /* correct top (in case of previous open call) */
                    continue;
                }

                case OpCode.OP_CLOSE: {
                    luaF_close(L, ra);
                    continue;
                }

                case OpCode.OP_CLOSURE: {
                    Proto   p;
                    Closure ncl;
                    int     nup, j;
                    p       = cl.p.p[GETARG_Bx(i)];
                    nup     = p.nups;
                    ncl     = luaF_newLclosure(L, nup, cl.env);
                    ncl.l.p = p;
                    setclvalue(L, ra, ncl);
                    for (j = 0; j < nup; j++)
                    {
                        Instruction u = ci.u.l.savedpc[0]; InstructionPtr.inc(ref ci.u.l.savedpc);
                        if (GET_OPCODE(u) == OpCode.OP_GETUPVAL)
                        {
                            ncl.l.upvals[j] = cl.upvals[GETARG_B(u)];
                        }
                        else
                        {
                            lua_assert(GET_OPCODE(u) == OpCode.OP_MOVE);
                            ncl.l.upvals[j] = luaF_findupval(L, base_ + GETARG_B(u));
                        }
                    }
                    //Protect(
                    //L.savedpc = InstructionPtr.Assign(pc);//FIXME:
                    luaC_checkGC(L);
                    base_ = ci.u.l.base_;
                    //);
                    continue;
                }

                case OpCode.OP_VARARG: {
                    int b = GETARG_B(i) - 1;
                    int j;
                    int n = cast_int(base_ - ci.func) - cl.p.numparams - 1;
                    if (b == LUA_MULTRET)
                    {
                        //Protect(
                        //L.savedpc = InstructionPtr.Assign(pc);//FIXME:
                        luaD_checkstack(L, n);
                        base_ = ci.u.l.base_;
                        //);
                        ra    = RA(L, base_, i);         /* previous call may change the stack */
                        b     = n;
                        L.top = ra + n;
                    }
                    for (j = 0; j < b; j++)
                    {
                        if (j < n)
                        {
                            setobjs2s(L, ra + j, base_ - n + j);
                        }
                        else
                        {
                            setnilvalue(ra + j);
                        }
                    }
                    continue;
                }

                case OpCode.OP_EXTRAARG: {
                    luaG_runerror(L, "bad opcode");
                    return;
                }
                }
                /* function changed (call/return): update pointers */
                lua_assert(ci == L.ci);
                cl    = clvalue(ci.func).l;
                k     = cl.p.k;
                base_ = ci.u.l.base_;
            }
        }
Ejemplo n.º 18
0
 internal static OpCode GET_OPCODE(InstructionPtr i)
 {
     return GET_OPCODE(i[0]);
 }
Ejemplo n.º 19
0
        }                                                                               //FIXME: added

        public static void SETARG_B(InstructionPtr i, int v)
        {
            setarg(i, v, POS_B, SIZE_B);
        }
Ejemplo n.º 20
0
        /*
        ** finish execution of an opcode interrupted by an yield
        */
        public static void luaV_finishOp(lua_State L)
        {
            CallInfo    ci    = L.ci;
            StkId       base_ = ci.u.l.base_;
            Instruction inst  = ci.u.l.savedpc[-1]; /* interrupted instruction */

            switch (GET_OPCODE(inst))               /* finish its execution */
            {
            case OpCode.OP_ADD:
            case OpCode.OP_SUB:
            case OpCode.OP_MUL:
            case OpCode.OP_DIV:
            case OpCode.OP_MOD:
            case OpCode.OP_POW:
            case OpCode.OP_UNM:
            case OpCode.OP_LEN:
            case OpCode.OP_GETGLOBAL:
            case OpCode.OP_GETTABLE:
            case OpCode.OP_SELF: {
                lua_TValue.dec(ref L.top);          //--L.top
                setobjs2s(L, base_ + GETARG_A(inst), L.top);
                break;
            }

            case OpCode.OP_LE:
            case OpCode.OP_LT:
            case OpCode.OP_EQ: {
                int res = l_isfalse(L.top - 1) != 0 ? 0 : 1;
                lua_TValue.dec(ref L.top);
                /* metamethod should not be called when operand is K */
                lua_assert(ISK(GETARG_B(inst)) == 0);
                if (GET_OPCODE(inst) == OpCode.OP_LE &&        /* "<=" using "<" instead? */
                    ttisnil(luaT_gettmbyobj(L, base_ + GETARG_B(inst), TMS.TM_LE)))
                {
                    res = (res != 0 ? 0 : 1);      /* invert result */
                }
                lua_assert(GET_OPCODE(ci.u.l.savedpc[0]) == OpCode.OP_JMP);
                if (res != GETARG_A(inst))                  /* condition failed? */
                {
                    InstructionPtr.inc(ref ci.u.l.savedpc); /* skip jump instruction */
                }
                break;
            }

            case OpCode.OP_CONCAT: {
                StkId top   = L.top - 1;             /* top when 'call_binTM' was called */
                int   b     = GETARG_B(inst);        /* first element to concatenate */
                int   total = top - 1 - (base_ + b); /* elements yet to concatenate */
                setobj2s(L, top - 2, top);           /* put TM result in proper position */
                if (total > 1)                       /* are there elements to concat? */
                {
                    L.top = top - 1;                 /* top is one after last element (at top-2) */
                    luaV_concat(L, total);           /* concat them (may yield again) */
                }
                /* move final result to final position */
                setobj2s(L, ci.u.l.base_ + GETARG_A(inst), L.top - 1);
                L.top = ci.top;        /* restore top */
                break;
            }

            case OpCode.OP_TFORCALL: {
                lua_assert(GET_OPCODE(ci.u.l.savedpc[0]) == OpCode.OP_TFORLOOP);
                L.top = ci.top;        /* correct top */
                break;
            }

            case OpCode.OP_CALL: {
                if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */
                {
                    L.top = ci.top;          /* adjust results */
                }
                break;
            }

            case OpCode.OP_TAILCALL:
            case OpCode.OP_SETGLOBAL:
            case OpCode.OP_SETTABLE:
                break;

            default: lua_assert(0);
                break;      //FIXME:added
            }
        }
Ejemplo n.º 21
0
 internal static OpCode GET_OPCODE(InstructionPtr i)
 {
     return(GET_OPCODE(i[0]));
 }
Ejemplo n.º 22
0
        private static void unroll(lua_State L)
        {
            for (;;)
            {
                Instruction inst;
                luaV_execute(L);                                /* execute down to higher C 'boundary' */
                if (L.ci == L.base_ci[0]) /* stack is empty? */ //FIXME:???==
                {
                    lua_assert(L.baseCcalls == G(L).nCcalls);
                    return;               /* coroutine finished normally */
                }
                L.baseCcalls--;           /* undo increment that allows yields */
                inst = L.savedpc[-1];     /* interrupted instruction */
                switch (GET_OPCODE(inst)) /* finish its execution */
                {
                case OpCode.OP_ADD:
                case OpCode.OP_SUB:
                case OpCode.OP_MUL:
                case OpCode.OP_DIV:
                case OpCode.OP_MOD:
                case OpCode.OP_POW:
                case OpCode.OP_UNM:
                case OpCode.OP_LEN:
                case OpCode.OP_GETGLOBAL:
                case OpCode.OP_GETTABLE:
                case OpCode.OP_SELF: {
                    setobjs2s(L, L.base_ + GETARG_A(inst), StkId.dec(ref L.top));     //FIXME:--
                    break;
                }

                case OpCode.OP_LE:
                case OpCode.OP_LT:
                case OpCode.OP_EQ: {
                    int res = l_isfalse(L.top - 1) == 0 ? 1 : 0;
                    StkId.dec(ref L.top);     //FIXME:--
                    /* metamethod should not be called when operand is K */
                    lua_assert(ISK(GETARG_B(inst)) == 0);
                    if (GET_OPCODE(inst) == OpCode.OP_LE &&      /* "<=" using "<" instead? */
                        ttisnil(luaT_gettmbyobj(L, L.base_ + GETARG_B(inst), TMS.TM_LE)))
                    {
                        res = (res == 0 ? 1 : 0);    /* invert result */
                    }
                    lua_assert(GET_OPCODE(L.savedpc[0]) == OpCode.OP_JMP);
                    if (res != GETARG_A(inst))      /* condition failed? */
                    {
                        InstructionPtr.inc(ref L.savedpc);
                    } /* skip jump instruction */                                         //FIXME:++
                    break;
                }

                case OpCode.OP_CONCAT: {
                    StkId top   = L.top - 1;                   /* top when __concat was called */
                    int   last  = cast_int(top - L.base_) - 2; /* last element and ... */
                    int   b     = GETARG_B(inst);              /* ... first element to concatenate */
                    int   total = last - b + 1;                /* number of elements to concatenate */
                    setobj2s(L, top - 2, top);                 /* put TM result in proper position */
                    L.top = L.ci.top;                          /* correct top */
                    if (total > 1)                             /* are there elements to concat? */
                    {
                        luaV_concat(L, total, last);           /* concat them (may yield again) */
                    }
                    /* move final result to final position */
                    setobj2s(L, L.base_ + GETARG_A(inst), L.base_ + b);
                    continue;
                }

                case OpCode.OP_TFORCALL: {
                    lua_assert(GET_OPCODE(L.savedpc[0]) == OpCode.OP_TFORLOOP);
                    L.top = L.ci.top;      /* correct top */
                    break;
                }

                case OpCode.OP_SETGLOBAL:
                case OpCode.OP_SETTABLE:
                    break;      /* nothing to be done */

                default: lua_assert(0);
                    break;    //FIXME:
                }
            }
        }
Ejemplo n.º 23
0
        }                                                                                 //FIXME: added

        public static void SETARG_Ax(InstructionPtr i, int v)
        {
            setarg(i, v, POS_Ax, SIZE_Ax);
        }
Ejemplo n.º 24
0
 public static int GETARG_Ax(InstructionPtr i)
 {
     return(GETARG_Ax(i[0]));
 }                                                                                 //FIXME: added
Ejemplo n.º 25
0
        }                                                                               //FIXME: added

        public static void SETARG_C(InstructionPtr i, int v)
        {
            setarg(i, v, POS_C, SIZE_C);
        }
Ejemplo n.º 26
0
 public static int pcRel(InstructionPtr pc, Proto p)
 {
     Debug.Assert(pc.codes == p.code);
     return(pc.pc - 1);
 }
Ejemplo n.º 27
0
		public static int PCRel(InstructionPtr pc, Proto p)
		{
			Debug.Assert(pc.codes == p.code);
			return pc.pc - 1;
		}
Ejemplo n.º 28
0
 internal static void SETARG_C(InstructionPtr i, int b)
 {
     i[0] = (Instruction)((i[0] & MASK0(SIZE_C, POS_C)) | ((b << POS_C) & MASK1(SIZE_C, POS_C)));
 }
Ejemplo n.º 29
0
 internal static void SET_OPCODE(InstructionPtr i, OpCode opcode)
 {
     SET_OPCODE(ref i.codes[i.pc], opcode);
 }
Ejemplo n.º 30
0
 public static void dojump(int i, CallInfo ci, lua_State L)
 {
     InstructionPtr.inc(ref ci.u.l.savedpc, i); luai_threadyield(L);
 }                                                                                                                                      //FIXME:
Ejemplo n.º 31
0
		private static void FixJump (FuncState fs, int pc, int dest) {
		  InstructionPtr jmp = new InstructionPtr(fs.f.code, pc);
		  int offset = dest-(pc+1);
		  LuaAssert(dest != NO_JUMP);
		  if (Math.Abs(offset) > MAXARG_sBx)
			LuaXSyntaxError(fs.ls, "control structure too long");
		  SETARG_sBx(jmp, offset);
		}
Ejemplo n.º 32
0
 internal static int GETARG_sBx(InstructionPtr i)
 {
     return GETARG_sBx(i[0]);
 }
Ejemplo n.º 33
0
		public static InstructionPtr Assign(InstructionPtr ptr)
		{
			if (ptr == null) return null;
			return new InstructionPtr(ptr.codes, ptr.pc);
		}
Ejemplo n.º 34
0
 internal static void SETARG_A(InstructionPtr i, int u)
 {
     i[0] = (Instruction)((i[0] & MASK0(SIZE_A, POS_A)) | ((u << POS_A) & MASK1(SIZE_A, POS_A)));
 }
Ejemplo n.º 35
0
		public static void dojump(LuaState L, InstructionPtr pc, int i) { pc.pc += i; LuaIThreadYield(L); }
Ejemplo n.º 36
0
 internal static void SETARG_sBx(InstructionPtr i, int b)
 {
     SETARG_Bx(i, b + MAXARG_sBx);
 }
Ejemplo n.º 37
0
 public static void dojump(lua_State L, InstructionPtr pc, int i)
 {
     pc.pc += i; luai_threadyield(L);
 }
Ejemplo n.º 38
0
		public static void LuaKNil (FuncState fs, int from, int n) {
		  InstructionPtr previous;
		  if (fs.pc > fs.lasttarget) {  /* no jumps to current position? */
			if (fs.pc == 0) {  /* function start? */
			  if (from >= fs.nactvar)
				return;  /* positions are already clean */
			}
			else {
			  previous = new InstructionPtr(fs.f.code, fs.pc-1);
			  if (GET_OPCODE(previous) == OpCode.OP_LOADNIL) {
				int pfrom = GETARG_A(previous);
				int pto = GETARG_B(previous);
				if (pfrom <= from && from <= pto+1) {  /* can connect both? */
				  if (from+n-1 > pto)
					SETARG_B(previous, from+n-1);
				  return;
				}
			  }
			}
		  }
		  LuaKCodeABC(fs, OpCode.OP_LOADNIL, from, from + n - 1, 0);  /* else no optimization */
		}
Ejemplo n.º 39
0
 public static void dojump(lua_State L, int i)
 {
     InstructionPtr.inc(ref L.savedpc, i); luai_threadyield(L);
 }
Ejemplo n.º 40
0
		private static InstructionPtr GetJumpControl (FuncState fs, int pc) {
		  InstructionPtr pi = new InstructionPtr(fs.f.code, pc);
		  if (pc >= 1 && (testTMode(GET_OPCODE(pi[-1]))!=0))
			return new InstructionPtr(pi.codes, pi.pc-1);
		  else
			return new InstructionPtr(pi.codes, pi.pc);
		}
Ejemplo n.º 41
0
 internal static void SET_OPCODE(InstructionPtr i, OpCode opcode)
 {
     SET_OPCODE(ref i.codes[i.pc], opcode);
 }
Ejemplo n.º 42
0
		public static InstructionPtr dec(ref InstructionPtr ptr)
		{
			InstructionPtr result = new InstructionPtr(ptr.codes, ptr.pc);
			ptr.pc--;
			return result;
		}
Ejemplo n.º 43
0
 internal static void SETARG_A(InstructionPtr i, int u)
 {
     i[0] = (Instruction)((i[0] & MASK0(SIZE_A, POS_A)) | ((u << POS_A) & MASK1(SIZE_A, POS_A)));
 }
Ejemplo n.º 44
0
 public static void dojump(lua_State L, InstructionPtr pc, int i)
 {
     pc.pc += i; luai_threadyield(L);
 }
Ejemplo n.º 45
0
 internal static void SETARG_Bx(InstructionPtr i, int b)
 {
     i[0] = (Instruction)((i[0] & MASK0(SIZE_Bx, POS_Bx)) | ((b << POS_Bx) & MASK1(SIZE_Bx, POS_Bx)));
 }
Ejemplo n.º 46
0
        public static void luaV_execute(lua_State L, int nexeccalls)
        {
            LClosure cl;
            StkId    base_;

            TValue[] k;
            /*const*/ InstructionPtr pc;

reentry:    /* entry point */
            lua_assert(isLua(L.ci));
            pc    = InstructionPtr.Assign(L.savedpc);
            cl    = clvalue(L.ci.func).l;
            base_ = L.base_;
            k     = cl.p.k;
            /* main loop of interpreter */
            for (;;)
            {
                /*const*/ Instruction i = InstructionPtr.inc(ref pc)[0];
                StkId ra;
                if (((L.hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) != 0) &&
                    (((--L.hookcount) == 0) || ((L.hookmask & LUA_MASKLINE) != 0)))
                {
                    traceexec(L, pc);
                    if (L.status == LUA_YIELD)          /* did hook yield? */
                    {
                        L.savedpc = new InstructionPtr(pc.codes, pc.pc - 1);
                        return;
                    }
                    base_ = L.base_;
                }
                /* warning!! several calls may realloc the stack and invalidate `ra' */
                ra = RA(L, base_, i);
                lua_assert(base_ == L.base_ && L.base_ == L.ci.base_);
                lua_assert(base_ <= L.top && ((L.top - L.stack) <= L.stacksize));
                lua_assert(L.top == L.ci.top || (luaG_checkopenop(i) != 0));
                //Dump(pc.pc, i);
                switch (GET_OPCODE(i))
                {
                case OpCode.OP_MOVE: {
                    setobjs2s(L, ra, RB(L, base_, i));
                    continue;
                }

                case OpCode.OP_LOADK: {
                    setobj2s(L, ra, KBx(L, i, k));
                    continue;
                }

                case OpCode.OP_LOADBOOL: {
                    setbvalue(ra, GETARG_B(i));
                    if (GETARG_C(i) != 0)
                    {
                        InstructionPtr.inc(ref pc);                                /* skip next instruction (if C) */
                    }
                    continue;
                }

                case OpCode.OP_LOADNIL: {
                    TValue rb = RB(L, base_, i);
                    do
                    {
                        setnilvalue(StkId.dec(ref rb));
                    } while (rb >= ra);
                    continue;
                }

                case OpCode.OP_GETUPVAL: {
                    int b = GETARG_B(i);
                    setobj2s(L, ra, cl.upvals[b].v);
                    continue;
                }

                case OpCode.OP_GETGLOBAL: {
                    TValue g  = new TValue();
                    TValue rb = KBx(L, i, k);
                    sethvalue(L, g, cl.env);
                    lua_assert(ttisstring(rb));
                    //Protect(
                    L.savedpc = InstructionPtr.Assign(pc);
                    luaV_gettable(L, g, rb, ra);
                    base_ = L.base_;
                    //);
                    L.savedpc = InstructionPtr.Assign(pc);
                    continue;
                }

                case OpCode.OP_GETTABLE: {
                    //Protect(
                    L.savedpc = InstructionPtr.Assign(pc);
                    luaV_gettable(L, RB(L, base_, i), RKC(L, base_, i, k), ra);
                    base_ = L.base_;
                    //);
                    L.savedpc = InstructionPtr.Assign(pc);
                    continue;
                }

                case OpCode.OP_SETGLOBAL: {
                    TValue g = new TValue();
                    sethvalue(L, g, cl.env);
                    lua_assert(ttisstring(KBx(L, i, k)));
                    //Protect(
                    L.savedpc = InstructionPtr.Assign(pc);
                    luaV_settable(L, g, KBx(L, i, k), ra);
                    base_ = L.base_;
                    //);
                    L.savedpc = InstructionPtr.Assign(pc);
                    continue;
                }

                case OpCode.OP_SETUPVAL: {
                    UpVal uv = cl.upvals[GETARG_B(i)];
                    setobj(L, uv.v, ra);
                    luaC_barrier(L, uv, ra);
                    continue;
                }

                case OpCode.OP_SETTABLE: {
                    //Protect(
                    L.savedpc = InstructionPtr.Assign(pc);
                    luaV_settable(L, ra, RKB(L, base_, i, k), RKC(L, base_, i, k));
                    base_ = L.base_;
                    //);
                    L.savedpc = InstructionPtr.Assign(pc);
                    continue;
                }

                case OpCode.OP_NEWTABLE: {
                    int b = GETARG_B(i);
                    int c = GETARG_C(i);
                    sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
                    //Protect(
                    L.savedpc = InstructionPtr.Assign(pc);
                    luaC_checkGC(L);
                    base_ = L.base_;
                    //);
                    L.savedpc = InstructionPtr.Assign(pc);
                    continue;
                }

                case OpCode.OP_SELF: {
                    StkId rb = RB(L, base_, i);
                    setobjs2s(L, ra + 1, rb);
                    //Protect(
                    L.savedpc = InstructionPtr.Assign(pc);
                    luaV_gettable(L, rb, RKC(L, base_, i, k), ra);
                    base_ = L.base_;
                    //);
                    L.savedpc = InstructionPtr.Assign(pc);
                    continue;
                }

                case OpCode.OP_ADD: {
                    arith_op(L, luai_numadd, TMS.TM_ADD, base_, i, k, ra, pc);
                    continue;
                }

                case OpCode.OP_SUB: {
                    arith_op(L, luai_numsub, TMS.TM_SUB, base_, i, k, ra, pc);
                    continue;
                }

                case OpCode.OP_MUL: {
                    arith_op(L, luai_nummul, TMS.TM_MUL, base_, i, k, ra, pc);
                    continue;
                }

                case OpCode.OP_DIV: {
                    arith_op(L, luai_numdiv, TMS.TM_DIV, base_, i, k, ra, pc);
                    continue;
                }

                case OpCode.OP_MOD: {
                    arith_op(L, luai_nummod, TMS.TM_MOD, base_, i, k, ra, pc);
                    continue;
                }

                case OpCode.OP_POW: {
                    arith_op(L, luai_numpow, TMS.TM_POW, base_, i, k, ra, pc);
                    continue;
                }

                case OpCode.OP_UNM: {
                    TValue rb = RB(L, base_, i);
                    if (ttisnumber(rb))
                    {
                        lua_Number nb = nvalue(rb);
                        setnvalue(ra, luai_numunm(nb));
                    }
                    else
                    {
                        //Protect(
                        L.savedpc = InstructionPtr.Assign(pc);
                        Arith(L, ra, rb, rb, TMS.TM_UNM);
                        base_ = L.base_;
                        //);
                        L.savedpc = InstructionPtr.Assign(pc);
                    }
                    continue;
                }

                case OpCode.OP_NOT: {
                    int res = l_isfalse(RB(L, base_, i)) == 0 ? 0 : 1;              /* next assignment may change this value */
                    setbvalue(ra, res);
                    continue;
                }

                case OpCode.OP_LEN: {
                    TValue rb = RB(L, base_, i);
                    switch (ttype(rb))
                    {
                    case LUA_TTABLE: {
                        setnvalue(ra, (lua_Number)luaH_getn(hvalue(rb)));
                        break;
                    }

                    case LUA_TSTRING: {
                        setnvalue(ra, (lua_Number)tsvalue(rb).len);
                        break;
                    }

                    default: {                /* try metamethod */
                        //Protect(
                        L.savedpc = InstructionPtr.Assign(pc);
                        if (call_binTM(L, rb, luaO_nilobject, ra, TMS.TM_LEN) == 0)
                        {
                            luaG_typeerror(L, rb, "get length of");
                        }
                        base_ = L.base_;
                        //)
                        break;
                    }
                    }
                    continue;
                }

                case OpCode.OP_CONCAT: {
                    int b = GETARG_B(i);
                    int c = GETARG_C(i);
                    //Protect(
                    L.savedpc = InstructionPtr.Assign(pc);
                    luaV_concat(L, c - b + 1, c); luaC_checkGC(L);
                    base_ = L.base_;
                    //);
                    setobjs2s(L, RA(L, base_, i), base_ + b);
                    continue;
                }

                case OpCode.OP_JMP: {
                    dojump(L, pc, GETARG_sBx(i));
                    continue;
                }

                case OpCode.OP_EQ: {
                    TValue rb = RKB(L, base_, i, k);
                    TValue rc = RKC(L, base_, i, k);
                    //Protect(
                    L.savedpc = InstructionPtr.Assign(pc);
                    if (equalobj(L, rb, rc) == GETARG_A(i))
                    {
                        dojump(L, pc, GETARG_sBx(pc[0]));
                    }
                    base_ = L.base_;
                    //);
                    InstructionPtr.inc(ref pc);
                    continue;
                }

                case OpCode.OP_LT: {
                    //Protect(
                    L.savedpc = InstructionPtr.Assign(pc);
                    if (luaV_lessthan(L, RKB(L, base_, i, k), RKC(L, base_, i, k)) == GETARG_A(i))
                    {
                        dojump(L, pc, GETARG_sBx(pc[0]));
                    }
                    base_ = L.base_;
                    //);
                    InstructionPtr.inc(ref pc);
                    continue;
                }

                case OpCode.OP_LE: {
                    //Protect(
                    L.savedpc = InstructionPtr.Assign(pc);
                    if (lessequal(L, RKB(L, base_, i, k), RKC(L, base_, i, k)) == GETARG_A(i))
                    {
                        dojump(L, pc, GETARG_sBx(pc[0]));
                    }
                    base_ = L.base_;
                    //);
                    InstructionPtr.inc(ref pc);
                    continue;
                }

                case OpCode.OP_TEST: {
                    if (l_isfalse(ra) != GETARG_C(i))
                    {
                        dojump(L, pc, GETARG_sBx(pc[0]));
                    }
                    InstructionPtr.inc(ref pc);
                    continue;
                }

                case OpCode.OP_TESTSET: {
                    TValue rb = RB(L, base_, i);
                    if (l_isfalse(rb) != GETARG_C(i))
                    {
                        setobjs2s(L, ra, rb);
                        dojump(L, pc, GETARG_sBx(pc[0]));
                    }
                    InstructionPtr.inc(ref pc);
                    continue;
                }

                case OpCode.OP_CALL: {
                    int b        = GETARG_B(i);
                    int nresults = GETARG_C(i) - 1;
                    if (b != 0)
                    {
                        L.top = ra + b;                      /* else previous instruction set top */
                    }
                    L.savedpc = InstructionPtr.Assign(pc);
                    switch (luaD_precall(L, ra, nresults))
                    {
                    case PCRLUA: {
                        nexeccalls++;
                        goto reentry;                  /* restart luaV_execute over new Lua function */
                    }

                    case PCRC: {
                        /* it was a C function (`precall' called it); adjust results */
                        if (nresults >= 0)
                        {
                            L.top = L.ci.top;
                        }
                        base_ = L.base_;
                        continue;
                    }

                    default: {
                        return;                  /* yield */
                    }
                    }
                }

                case OpCode.OP_TAILCALL: {
                    int b = GETARG_B(i);
                    if (b != 0)
                    {
                        L.top = ra + b;                      /* else previous instruction set top */
                    }
                    L.savedpc = InstructionPtr.Assign(pc);
                    lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
                    switch (luaD_precall(L, ra, LUA_MULTRET))
                    {
                    case PCRLUA: {
                        /* tail call: put new frame in place of previous one */
                        CallInfo ci = L.ci - 1;                  /* previous frame */
                        int      aux;
                        StkId    func  = ci.func;
                        StkId    pfunc = (ci + 1).func;             /* previous function index */
                        if (L.openupval != null)
                        {
                            luaF_close(L, ci.base_);
                        }
                        L.base_ = ci.base_ = ci.func + (ci[1].base_ - pfunc);
                        for (aux = 0; pfunc + aux < L.top; aux++)                /* move frame down */
                        {
                            setobjs2s(L, func + aux, pfunc + aux);
                        }
                        ci.top = L.top = func + aux;                /* correct top */
                        lua_assert(L.top == L.base_ + clvalue(func).l.p.maxstacksize);
                        ci.savedpc = InstructionPtr.Assign(L.savedpc);
                        ci.tailcalls++;                  /* one more call lost */
                        CallInfo.dec(ref L.ci);          /* remove new frame */
                        goto reentry;
                    }

                    case PCRC: {                /* it was a C function (`precall' called it) */
                        base_ = L.base_;
                        continue;
                    }

                    default: {
                        return;                  /* yield */
                    }
                    }
                }

                case OpCode.OP_RETURN: {
                    int b = GETARG_B(i);
                    if (b != 0)
                    {
                        L.top = ra + b - 1;
                    }
                    if (L.openupval != null)
                    {
                        luaF_close(L, base_);
                    }
                    L.savedpc = InstructionPtr.Assign(pc);
                    b         = luaD_poscall(L, ra);
                    if (--nexeccalls == 0) /* was previous function running `here'? */
                    {
                        return;            /* no: return */
                    }
                    else                   /* yes: continue its execution */
                    {
                        if (b != 0)
                        {
                            L.top = L.ci.top;
                        }
                        lua_assert(isLua(L.ci));
                        lua_assert(GET_OPCODE(L.ci.savedpc[-1]) == OpCode.OP_CALL);
                        goto reentry;
                    }
                }

                case OpCode.OP_FORLOOP: {
                    lua_Number step  = nvalue(ra + 2);
                    lua_Number idx   = luai_numadd(nvalue(ra), step);           /* increment index */
                    lua_Number limit = nvalue(ra + 1);
                    if (luai_numlt(0, step) ? luai_numle(idx, limit)
                                                                                : luai_numle(limit, idx))
                    {
                        dojump(L, pc, GETARG_sBx(i));  /* jump back */
                        setnvalue(ra, idx);            /* update internal index... */
                        setnvalue(ra + 3, idx);        /* ...and external index */
                    }
                    continue;
                }

                case OpCode.OP_FORPREP: {
                    TValue init   = ra;
                    TValue plimit = ra + 1;
                    TValue pstep  = ra + 2;
                    L.savedpc = InstructionPtr.Assign(pc);              /* next steps may throw errors */
                    if (tonumber(ref init, ra) == 0)
                    {
                        luaG_runerror(L, LUA_QL("for") + " initial value must be a number");
                    }
                    else if (tonumber(ref plimit, ra + 1) == 0)
                    {
                        luaG_runerror(L, LUA_QL("for") + " limit must be a number");
                    }
                    else if (tonumber(ref pstep, ra + 2) == 0)
                    {
                        luaG_runerror(L, LUA_QL("for") + " step must be a number");
                    }
                    setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
                    dojump(L, pc, GETARG_sBx(i));
                    continue;
                }

                case OpCode.OP_TFORLOOP: {
                    StkId cb = ra + 3;              /* call base */
                    setobjs2s(L, cb + 2, ra + 2);
                    setobjs2s(L, cb + 1, ra + 1);
                    setobjs2s(L, cb, ra);
                    L.top = cb + 3;            /* func. + 2 args (state and index) */
                    //Protect(
                    L.savedpc = InstructionPtr.Assign(pc);
                    luaD_call(L, cb, GETARG_C(i));
                    base_ = L.base_;
                    //);
                    L.top = L.ci.top;
                    cb    = RA(L, base_, i) + 3;          /* previous call may change the stack */
                    if (!ttisnil(cb))                     /* continue loop? */
                    {
                        setobjs2s(L, cb - 1, cb);         /* save control variable */
                        dojump(L, pc, GETARG_sBx(pc[0])); /* jump back */
                    }
                    InstructionPtr.inc(ref pc);
                    continue;
                }

                case OpCode.OP_SETLIST: {
                    int   n = GETARG_B(i);
                    int   c = GETARG_C(i);
                    int   last;
                    Table h;
                    if (n == 0)
                    {
                        n     = cast_int(L.top - ra) - 1;
                        L.top = L.ci.top;
                    }
                    if (c == 0)
                    {
                        c = cast_int(pc[0]);
                        InstructionPtr.inc(ref pc);
                    }
                    runtime_check(L, ttistable(ra));
                    h    = hvalue(ra);
                    last = ((c - 1) * LFIELDS_PER_FLUSH) + n;
                    if (last > h.sizearray)              /* needs more space? */
                    {
                        luaH_resizearray(L, h, last);    /* pre-alloc it at once */
                    }
                    for (; n > 0; n--)
                    {
                        TValue val = ra + n;
                        setobj2t(L, luaH_setnum(L, h, last--), val);
                        luaC_barriert(L, h, val);
                    }
                    continue;
                }

                case OpCode.OP_CLOSE: {
                    luaF_close(L, ra);
                    continue;
                }

                case OpCode.OP_CLOSURE: {
                    Proto   p;
                    Closure ncl;
                    int     nup, j;
                    p       = cl.p.p[GETARG_Bx(i)];
                    nup     = p.nups;
                    ncl     = luaF_newLclosure(L, nup, cl.env);
                    ncl.l.p = p;
                    for (j = 0; j < nup; j++, InstructionPtr.inc(ref pc))
                    {
                        if (GET_OPCODE(pc[0]) == OpCode.OP_GETUPVAL)
                        {
                            ncl.l.upvals[j] = cl.upvals[GETARG_B(pc[0])];
                        }
                        else
                        {
                            lua_assert(GET_OPCODE(pc[0]) == OpCode.OP_MOVE);
                            ncl.l.upvals[j] = luaF_findupval(L, base_ + GETARG_B(pc[0]));
                        }
                    }
                    setclvalue(L, ra, ncl);
                    //Protect(
                    L.savedpc = InstructionPtr.Assign(pc);
                    luaC_checkGC(L);
                    base_ = L.base_;
                    //);
                    continue;
                }

                case OpCode.OP_VARARG: {
                    int      b = GETARG_B(i) - 1;
                    int      j;
                    CallInfo ci = L.ci;
                    int      n  = cast_int(ci.base_ - ci.func) - cl.p.numparams - 1;
                    if (b == LUA_MULTRET)
                    {
                        //Protect(
                        L.savedpc = InstructionPtr.Assign(pc);
                        luaD_checkstack(L, n);
                        base_ = L.base_;
                        //);
                        ra    = RA(L, base_, i);         /* previous call may change the stack */
                        b     = n;
                        L.top = ra + n;
                    }
                    for (j = 0; j < b; j++)
                    {
                        if (j < n)
                        {
                            setobjs2s(L, ra + j, ci.base_ - n + j);
                        }
                        else
                        {
                            setnilvalue(ra + j);
                        }
                    }
                    continue;
                }
                }
            }
        }
Ejemplo n.º 47
0
 internal static int GETARG_sBx(InstructionPtr i)
 {
     return(GETARG_sBx(i[0]));
 }