static void GCTM (lua_State *L, int propagateerrors) { global_State *g = G(L); const TValue *tm; TValue v; setgcovalue(L, &v, udata2finalize(g)); tm = luaT_gettmbyobj(L, &v, TM_GC); if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ int status; lu_byte oldah = L->allowhook; int running = g->gcrunning; L->allowhook = 0; /* stop debug hooks during GC metamethod */ g->gcrunning = 0; /* avoid GC steps */ setobj2s(L, L->top, tm); /* push finalizer... */ setobj2s(L, L->top + 1, &v); /* ... and its argument */ L->top += 2; /* and (next line) call the finalizer */ status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); L->allowhook = oldah; /* restore hooks */ g->gcrunning = running; /* restore state */ if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ if (status == LUA_ERRRUN) { /* is there an error object? */ const char *msg = (ttisstring(L->top - 1)) ? svalue(L->top - 1) : "no message"; luaO_pushfstring(L, "error in __gc metamethod (%s)", msg); status = LUA_ERRGCMM; /* error in __gc metamethod */ } luaD_throw(L, status); /* re-throw error */ } } }
static void Arith (lua_State *L, StkId ra, const TObject *rb, const TObject *rc, TMS op) { TObject tempb, tempc; const TObject *b, *c; if ((b = luaV_tonumber(rb, &tempb)) != NULL && (c = luaV_tonumber(rc, &tempc)) != NULL) { switch (op) { case TM_ADD: setnvalue(ra, nvalue(b) + nvalue(c)); break; case TM_SUB: setnvalue(ra, nvalue(b) - nvalue(c)); break; case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break; case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break; case TM_POW: { const TObject *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_POW]); ptrdiff_t res = savestack(L, ra); if (!ttisfunction(f)) luaG_runerror(L, "`__pow' (`^' operator) is not a function"); callTMres(L, f, b, c); ra = restorestack(L, res); /* previous call may change stack */ setobjs2s(ra, L->top); break; } default: lua_assert(0); break; } } else if (!call_binTM(L, rb, rc, ra, op)) luaG_aritherror(L, rb, rc); }
/* ** If function yielded, its 'func' can be in the 'extra' field. The ** next function restores 'func' to its correct value for debugging ** purposes. (It exchanges 'func' and 'extra'; so, when called again, ** after debugging, it also "re-restores" ** 'func' to its altered value. */ static void swapextra (lua_State *L) { if (L->status == LUA_YIELD) { CallInfo *ci = L->ci; /* get function that yielded */ StkId temp = ci->func; /* exchange its 'func' and 'extra' values */ ci->func = restorestack(L, ci->extra); ci->extra = savestack(L, temp); } }
static void Arith (lua_State *L, StkId ra, const TValue *rb, const TValue *rc, TMS op) { TValue tempb, tempc; const TValue *b, *c; if ((b = luaV_tonumber(rb, &tempb)) != NULL && (c = luaV_tonumber(rc, &tempc)) != NULL) { lua_Number nb = nvalue(b), nc = nvalue(c); switch (op) { case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; case TM_DIV: setnvalue(ra, luai_lnumdiv(nb, nc)); break; case TM_MOD: setnvalue(ra, luai_lnummod(nb, nc)); break; case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; default: lua_assert(0); break; } } else { ptrdiff_t br = savestack(L, rb); ptrdiff_t cr = savestack(L, rc); if (!call_binTM(L, rb, rc, ra, op)) { luaG_aritherror(L, restorestack(L, br), restorestack(L, cr)); } } }
void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { switch (errcode) { case LUA_ERRMEM: { ptrdiff_t oldtopr = savestack(L, oldtop); setsvalue2s(L, restorestack(L, oldtopr), luaS_newliteral(L, MEMERRMSG)); break; } case LUA_ERRERR: { ptrdiff_t oldtopr = savestack(L, oldtop); setsvalue2s(L, restorestack(L, oldtopr), luaS_newliteral(L, "error in error handling")); break; } case LUA_ERRSYNTAX: case LUA_ERRRUN: { setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ break; } } L->top = oldtop + 1; }
static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, StkId res, TMS event) { ptrdiff_t result = savestack(L, res); const TObject *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ if (ttisnil(tm)) tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ if (!ttisfunction(tm)) return 0; callTMres(L, tm, p1, p2); res = restorestack(L, result); /* previous call may change stack */ setobjs2s(res, L->top); return 1; }
int luaV_tostring (lua_State *L, StkId obj) { if (!ttisnumber(obj)) return 0; else { char s[LUAI_MAXNUMBER2STR]; ptrdiff_t objr = savestack(L, obj); lua_Number n = nvalue(obj); lua_number2str(s, n); setsvalue2s(L, restorestack(L, objr), luaS_new(L, s)); return 1; } }
static void callTMres (lua_State *L, StkId res, const TValue *f, const TValue *p1, const TValue *p2) { ptrdiff_t result = savestack(L, res); setobj2s(L, L->top, f); /* push function */ setobj2s(L, L->top+1, p1); /* 1st argument */ setobj2s(L, L->top+2, p2); /* 2nd argument */ luaD_checkstack(L, 3); L->top += 3; luaD_call(L, L->top - 3, 1); res = restorestack(L, result); L->top--; setobjs2s(L, res, L->top); }
/* Parse a number literal. */ static void lex_number(LexState *ls) { StrScanFmt fmt; TValue *tv = &ls->tokenval; int c, xp = 'e'; if (ls->current == '-' || ls->current == '+') { save_and_next(ls); } if ((c = ls->current) == '0') { save_and_next(ls); if ((ls->current | 0x20) == 'x') xp = 'p'; } while (lj_char_isident(ls->current) || ls->current == '.' || ((ls->current == '-' || ls->current == '+') && (c | 0x20) == xp)) { c = ls->current; save_and_next(ls); } save(ls, '\0'); fmt = lj_strscan_scan((const uint8_t *)ls->sb.buf, tv, (LJ_DUALNUM ? STRSCAN_OPT_TOINT : STRSCAN_OPT_TONUM) | (LJ_HASFFI ? (STRSCAN_OPT_LL|STRSCAN_OPT_IMAG) : 0)); ls->token = TK_number; if (LJ_DUALNUM && fmt == STRSCAN_INT) { setitype(tv, LJ_TISNUM); } else if (fmt == STRSCAN_NUM) { /* Already in correct format. */ #if LJ_HASFFI } else if (fmt != STRSCAN_ERROR) { lua_State *L = ls->L; GCcdata *cd; lua_assert(fmt == STRSCAN_I64 || fmt == STRSCAN_U64 || fmt == STRSCAN_IMAG); if (!ctype_ctsG(G(L))) { ptrdiff_t oldtop = savestack(L, L->top); luaopen_ffi(L); /* Load FFI library on-demand. */ L->top = restorestack(L, oldtop); } if (fmt == STRSCAN_IMAG) { cd = lj_cdata_new_(L, CTID_COMPLEX_DOUBLE, 2*sizeof(double)); ((double *)cdataptr(cd))[0] = 0; ((double *)cdataptr(cd))[1] = numV(tv); } else { cd = lj_cdata_new_(L, fmt==STRSCAN_I64 ? CTID_INT64 : CTID_UINT64, 8); *(uint64_t *)cdataptr(cd) = tv->u64; } lj_parse_keepcdata(ls, tv, cd); #endif } else { lua_assert(fmt == STRSCAN_ERROR); lj_lex_error(ls, TK_number, LJ_ERR_XNUMBER); } }
static int precall(ktap_state *ks, StkId func, int nresults) { ktap_cfunction f; ktap_callinfo *ci; ktap_proto *p; StkId base; ptrdiff_t funcr = savestack(ks, func); int n; switch (ttype(func)) { case KTAP_TLCF: /* light C function */ f = fvalue(func); goto CFUNC; case KTAP_TCCL: /* C closure */ f = clcvalue(func)->f; CFUNC: checkstack(ks, KTAP_MINSTACK); ci = next_ci(ks); ci->nresults = nresults; ci->func = restorestack(ks, funcr); ci->top = ks->top + KTAP_MINSTACK; ci->callstatus = 0; n = (*f)(ks); poscall(ks, ks->top - n); return 1; case KTAP_TLCL: p = CLVALUE(func)->p; checkstack(ks, p->maxstacksize); func = restorestack(ks, funcr); n = (int)(ks->top - func) - 1; /* number of real arguments */ /* complete missing arguments */ for (; n < p->numparams; n++) setnilvalue(ks->top++); base = (!p->is_vararg) ? func + 1 : adjust_varargs(ks, p, n); ci = next_ci(ks); ci->nresults = nresults; ci->func = func; ci->u.l.base = base; ci->top = base + p->maxstacksize; ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus = CIST_KTAP; ks->top = ci->top; return 0; default: kp_error(ks, "attempt to call nil function\n"); } return 0; }
/* Find error function for runtime errors. Requires an extra stack traversal. */ static ptrdiff_t finderrfunc(lua_State *L) { cTValue *frame = L->base-1, *bot = tvref(L->stack); void *cf = L->cframe; while (frame > bot && cf) { while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ if (frame >= restorestack(L, -cframe_nres(cf))) break; if (cframe_errfunc(cf) >= 0) /* Error handler not inherited (-1)? */ return cframe_errfunc(cf); cf = cframe_prev(cf); /* Else unwind cframe and continue searching. */ if (cf == NULL) return 0; } switch (frame_typep(frame)) { case FRAME_LUA: case FRAME_LUAP: frame = frame_prevl(frame); break; case FRAME_C: cf = cframe_prev(cf); /* fallthrough */ case FRAME_VARG: frame = frame_prevd(frame); break; case FRAME_CONT: #if LJ_HASFFI if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) cf = cframe_prev(cf); #endif frame = frame_prevd(frame); break; case FRAME_CP: if (cframe_canyield(cf)) return 0; if (cframe_errfunc(cf) >= 0) return cframe_errfunc(cf); frame = frame_prevd(frame); break; case FRAME_PCALL: case FRAME_PCALLH: if (frame_ftsz(frame) >= (ptrdiff_t)(2*sizeof(TValue))) /* xpcall? */ return savestack(L, frame-1); /* Point to xpcall's errorfunc. */ return 0; default: lua_assert(0); return 0; } } return 0; }
void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, TValue *p3, int hasres) { ptrdiff_t result = savestack(L, p3); setobj2s(L, L->top++, f); /* push function (assume EXTRA_STACK) */ setobj2s(L, L->top++, p1); /* 1st argument */ setobj2s(L, L->top++, p2); /* 2nd argument */ if (!hasres) /* no result? 'p3' is third argument */ setobj2s(L, L->top++, p3); /* 3rd argument */ /* metamethod may yield only when called from Lua code */ luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); if (hasres) { /* if has result, move it to its place */ p3 = restorestack(L, result); setobjs2s(L, p3, --L->top); } }
/* Find error function for runtime errors. Requires an extra stack traversal. */ static ptrdiff_t finderrfunc(lua_State *L) { cTValue *frame = L->base-1, *bot = tvref(L->stack)+LJ_FR2; void *cf = L->cframe; while (frame > bot && cf) { while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ if (frame >= restorestack(L, -cframe_nres(cf))) break; if (cframe_errfunc(cf) >= 0) /* Error handler not inherited (-1)? */ return cframe_errfunc(cf); cf = cframe_prev(cf); /* Else unwind cframe and continue searching. */ if (cf == NULL) return 0; } switch (frame_typep(frame)) { case FRAME_LUA: case FRAME_LUAP: frame = frame_prevl(frame); break; case FRAME_C: cf = cframe_prev(cf); /* fallthrough */ case FRAME_VARG: frame = frame_prevd(frame); break; case FRAME_CONT: if (frame_iscont_fficb(frame)) cf = cframe_prev(cf); frame = frame_prevd(frame); break; case FRAME_CP: if (cframe_canyield(cf)) return 0; if (cframe_errfunc(cf) >= 0) return cframe_errfunc(cf); frame = frame_prevd(frame); break; case FRAME_PCALL: case FRAME_PCALLH: if (frame_func(frame_prevd(frame))->c.ffid == FF_xpcall) return savestack(L, frame_prevd(frame)+1); /* xpcall's errorfunc. */ return 0; default: lua_assert(0); return 0; } } return 0; }
void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, StkId res) { ptrdiff_t result = savestack(L, res); StkId func = L->top; setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ setobj2s(L, func + 1, p1); /* 1st argument */ setobj2s(L, func + 2, p2); /* 2nd argument */ L->top += 3; /* metamethod may yield only when called from Lua code */ if (isLuacode(L->ci)) luaD_call(L, func, 1); else luaD_callnoyield(L, func, 1); res = restorestack(L, result); setobjs2s(L, res, --L->top); /* move result to its place */ }
ptrdiff_t lj_vmevent_prepare(lua_State *L, VMEvent ev) { global_State *g = G(L); GCstr *s = lj_str_newlit(L, LJ_VMEVENTS_REGKEY); cTValue *tv = lj_tab_getstr(tabV(registry(L)), s); if (tvistab(tv)) { int hash = VMEVENT_HASH(ev); tv = lj_tab_getint(tabV(tv), hash); if (tv && tvisfunc(tv)) { lj_state_checkstack(L, LUA_MINSTACK); setfuncV(L, L->top++, funcV(tv)); return savestack(L, L->top); } } g->vmevmask &= ~VMEVENT_MASK(ev); /* No handler: cache this fact. */ return 0; }
/* 调用元操作 * L 虚拟机状态 * f 函数地址 * p1 函数第一个参数 * p2 函数第二个参数 * p3 函数的第三个参数 * hasres 是否存在第三个参数 */ static void callTM (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, TValue *p3, int hasres) { ptrdiff_t result = savestack(L, p3); /* 保存栈 */ setobj2s(L, L->top++, f); /* push function */ /* 元函数地址 */ setobj2s(L, L->top++, p1); /* 1st argument */ /* 参数1 */ setobj2s(L, L->top++, p2); /* 2nd argument */ /* 参数2 */ /* 如果hasres是1则压入第三个参数 */ if (!hasres) /* no result? 'p3' is third argument */ setobj2s(L, L->top++, p3); /* 3rd argument */ /* metamethod may yield only when called from Lua code */ /* 当从lua代码中调用元方法也许被挂起 */ luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); /* * 如果有第三个参数 */ if (hasres) { /* if has result, move it to its place */ p3 = restorestack(L, result); setobjs2s(L, p3, --L->top); } }
void luaV_execute (lua_State *L, int nexeccalls) { LClosure *cl; StkId base; TValue *k; const Instruction *pc; reentry: /* entry point */ lua_assert(isLua(L->ci)); pc = L->savedpc; cl = &clvalue(L->ci->func)->l; base = L->base; k = cl->p->k; /* main loop of interpreter */ for (;;) { const Instruction i = *pc++; StkId ra; if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { traceexec(L, pc); if (L->status == LUA_YIELD) { /* did hook yield? */ L->savedpc = pc - 1; return; } base = L->base; } /* warning!! several calls may realloc the stack and invalidate `ra' */ ra = RA(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)); switch (GET_OPCODE(i)) { case OP_MOVE: { setobjs2s(L, ra, RB(i)); continue; } case OP_LOADK: { setobj2s(L, ra, KBx(i)); continue; } case OP_LOADBOOL: { setbvalue(ra, GETARG_B(i)); if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ continue; } case OP_LOADNIL: { TValue *rb = RB(i); do { setnilvalue(rb--); } while (rb >= ra); continue; } case OP_GETUPVAL: { int b = GETARG_B(i); setobj2s(L, ra, cl->upvals[b]->v); continue; } case OP_GETGLOBAL: { TValue g; TValue *rb = KBx(i); sethvalue(L, &g, cl->env); lua_assert(ttisstring(rb)); Protect(luaV_gettable(L, &g, rb, ra)); continue; } case OP_GETTABLE: { Protect(luaV_gettable(L, RB(i), RKC(i), ra)); continue; } case OP_SETGLOBAL: { TValue g; sethvalue(L, &g, cl->env); lua_assert(ttisstring(KBx(i))); Protect(luaV_settable(L, &g, KBx(i), ra)); continue; } case OP_SETUPVAL: { UpVal *uv = cl->upvals[GETARG_B(i)]; setobj(L, uv->v, ra); luaC_barrier(L, uv, ra); continue; } case OP_SETTABLE: { Protect(luaV_settable(L, ra, RKB(i), RKC(i))); continue; } case OP_NEWTABLE: { int b = GETARG_B(i); int c = GETARG_C(i); Table *h; Protect(h = luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); sethvalue(L, RA(i), h); Protect(luaC_checkGC(L)); continue; } case OP_SELF: { StkId rb = RB(i); setobjs2s(L, ra+1, rb); Protect(luaV_gettable(L, rb, RKC(i), ra)); continue; } case OP_ADD: { arith_op(luai_numadd, TM_ADD); continue; } case OP_SUB: { arith_op(luai_numsub, TM_SUB); continue; } case OP_MUL: { arith_op(luai_nummul, TM_MUL); continue; } case OP_DIV: { arith_op(luai_lnumdiv, TM_DIV); continue; } case OP_MOD: { arith_op(luai_lnummod, TM_MOD); continue; } case OP_POW: { arith_op(luai_numpow, TM_POW); continue; } case OP_UNM: { TValue *rb = RB(i); if (ttisnumber(rb)) { lua_Number nb = nvalue(rb); setnvalue(ra, luai_numunm(nb)); } else { Protect(Arith(L, ra, rb, rb, TM_UNM)); } continue; } case OP_NOT: { int res = l_isfalse(RB(i)); /* next assignment may change this value */ setbvalue(ra, res); continue; } case OP_LEN: { const TValue *rb = RB(i); switch (ttype(rb)) { case LUA_TTABLE: case LUA_TROTABLE: { setnvalue(ra, ttistable(rb) ? cast_num(luaH_getn(hvalue(rb))) : cast_num(luaH_getn_ro(rvalue(rb)))); break; } case LUA_TSTRING: { setnvalue(ra, cast_num(tsvalue(rb)->len)); break; } default: { /* try metamethod */ ptrdiff_t br = savestack(L, rb); Protect( if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) luaG_typeerror(L, restorestack(L, br), "get length of"); ) } } continue; } case OP_CONCAT: { int b = GETARG_B(i); int c = GETARG_C(i); Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); setobjs2s(L, RA(i), base+b); continue; } case OP_JMP: { dojump(L, pc, GETARG_sBx(i)); continue; } case OP_EQ: { TValue *rb = RKB(i); TValue *rc = RKC(i); Protect( if (equalobj(L, rb, rc) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; } case OP_LT: { Protect( if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; } case OP_LE: { Protect( if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; }
/* Load FFI library on-demand. Needed if we create cdata objects. */ static void lex_loadffi(lua_State *L) { ptrdiff_t oldtop = savestack(L, L->top); luaopen_ffi(L); L->top = restorestack(L, oldtop); }
/* Restore interpreter state from exit state with the help of a snapshot. */ const BCIns *lj_snap_restore(jit_State *J, void *exptr) { ExitState *ex = (ExitState *)exptr; SnapNo snapno = J->exitno; /* For now, snapno == exitno. */ GCtrace *T = traceref(J, J->parent); SnapShot *snap = &T->snap[snapno]; MSize n, nent = snap->nent; SnapEntry *map = &T->snapmap[snap->mapofs]; SnapEntry *flinks = map + nent + snap->depth; int32_t ftsz0; BCReg nslots = snap->nslots; TValue *frame; BloomFilter rfilt = snap_renamefilter(T, snapno); const BCIns *pc = snap_pc(map[nent]); lua_State *L = J->L; /* Set interpreter PC to the next PC to get correct error messages. */ setcframe_pc(cframe_raw(L->cframe), pc+1); /* Make sure the stack is big enough for the slots from the snapshot. */ if (LJ_UNLIKELY(L->base + nslots > tvref(L->maxstack))) { L->top = curr_topL(L); lj_state_growstack(L, nslots - curr_proto(L)->framesize); } /* Fill stack slots with data from the registers and spill slots. */ frame = L->base-1; ftsz0 = frame_ftsz(frame); /* Preserve link to previous frame in slot #0. */ for (n = 0; n < nent; n++) { SnapEntry sn = map[n]; IRRef ref = snap_ref(sn); BCReg s = snap_slot(sn); TValue *o = &frame[s]; /* Stack slots are relative to start frame. */ IRIns *ir = &T->ir[ref]; if (irref_isk(ref)) { /* Restore constant slot. */ lj_ir_kvalue(L, o, ir); if ((sn & (SNAP_CONT|SNAP_FRAME))) { /* Overwrite tag with frame link. */ o->fr.tp.ftsz = s != 0 ? (int32_t)*flinks-- : ftsz0; if ((sn & SNAP_FRAME)) { GCfunc *fn = ir_kfunc(ir); if (isluafunc(fn)) { MSize framesize = funcproto(fn)->framesize; L->base = ++o; if (LJ_UNLIKELY(o + framesize > tvref(L->maxstack))) { ptrdiff_t fsave = savestack(L, frame); L->top = o; lj_state_growstack(L, framesize); /* Grow again. */ frame = restorestack(L, fsave); } } } } } else if (!(sn & SNAP_NORESTORE)) { IRType1 t = ir->t; RegSP rs = ir->prev; lua_assert(!(sn & (SNAP_CONT|SNAP_FRAME))); if (LJ_UNLIKELY(bloomtest(rfilt, ref))) rs = snap_renameref(T, snapno, ref, rs); if (ra_hasspill(regsp_spill(rs))) { /* Restore from spill slot. */ int32_t *sps = &ex->spill[regsp_spill(rs)]; if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) { o->u32.lo = (uint32_t)*sps; } else if (irt_isinteger(t)) { setintV(o, *sps); #if !LJ_SOFTFP } else if (irt_isnum(t)) { o->u64 = *(uint64_t *)sps; #endif #if LJ_64 } else if (irt_islightud(t)) { /* 64 bit lightuserdata which may escape already has the tag bits. */ o->u64 = *(uint64_t *)sps; #endif } else { lua_assert(!irt_ispri(t)); /* PRI refs never have a spill slot. */ setgcrefi(o->gcr, *sps); setitype(o, irt_toitype(t)); } } else { /* Restore from register. */ Reg r = regsp_reg(rs); lua_assert(ra_hasreg(r)); if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) { o->u32.lo = (uint32_t)ex->gpr[r-RID_MIN_GPR]; } else if (irt_isinteger(t)) { setintV(o, (int32_t)ex->gpr[r-RID_MIN_GPR]); #if !LJ_SOFTFP } else if (irt_isnum(t)) { setnumV(o, ex->fpr[r-RID_MIN_FPR]); #endif #if LJ_64 } else if (irt_islightud(t)) { /* 64 bit lightuserdata which may escape already has the tag bits. */ o->u64 = ex->gpr[r-RID_MIN_GPR]; #endif } else { if (!irt_ispri(t)) setgcrefi(o->gcr, ex->gpr[r-RID_MIN_GPR]); setitype(o, irt_toitype(t)); } } if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) { rs = (ir+1)->prev; if (LJ_UNLIKELY(bloomtest(rfilt, ref+1))) rs = snap_renameref(T, snapno, ref+1, rs); o->u32.hi = (ra_hasspill(regsp_spill(rs))) ? (uint32_t)*&ex->spill[regsp_spill(rs)] : (uint32_t)ex->gpr[regsp_reg(rs)-RID_MIN_GPR]; } } } switch (bc_op(*pc)) { case BC_CALLM: case BC_CALLMT: case BC_RETM: case BC_TSETM: L->top = frame + nslots; break; default: L->top = curr_topL(L); break; } lua_assert(map + nent == flinks); return pc; }