/* Save current trace by copying and compacting it. */ static void trace_save(jit_State *J) { size_t sztr = ((sizeof(GCtrace)+7)&~7); size_t szins = (J->cur.nins-J->cur.nk)*sizeof(IRIns); size_t sz = sztr + szins + J->cur.nsnap*sizeof(SnapShot) + J->cur.nsnapmap*sizeof(SnapEntry); GCtrace *T = lj_mem_newt(J->L, (MSize)sz, GCtrace); char *p = (char *)T + sztr; memcpy(T, &J->cur, sizeof(GCtrace)); setgcrefr(T->nextgc, J2G(J)->gc.root); setgcrefp(J2G(J)->gc.root, T); newwhite(J2G(J), T); T->gct = ~LJ_TTRACE; T->ir = (IRIns *)p - J->cur.nk; memcpy(p, J->cur.ir+J->cur.nk, szins); p += szins; TRACE_APPENDVEC(snap, nsnap, SnapShot) TRACE_APPENDVEC(snapmap, nsnapmap, SnapEntry) J->cur.traceno = 0; setgcrefp(J->trace[T->traceno], T); lj_gc_barriertrace(J2G(J), T->traceno); lj_gdbjit_addtrace(J, T); #ifdef LUAJIT_USE_PERFTOOLS perftools_addtrace(T); #endif }
/* Find existing open upvalue for a stack slot or create a new one. */ static GCupval *func_finduv(lua_State *L, TValue *slot) { global_State *g = G(L); GCRef *pp = &L->openupval; GCupval *p; GCupval *uv; /* Search the sorted list of open upvalues. */ while (gcref(*pp) != NULL && uvval((p = gco2uv(gcref(*pp)))) >= slot) { lua_assert(!p->closed && uvval(p) != &p->tv); if (uvval(p) == slot) { /* Found open upvalue pointing to same slot? */ if (isdead(g, obj2gco(p))) /* Resurrect it, if it's dead. */ flipwhite(obj2gco(p)); return p; } pp = &p->nextgc; } /* No matching upvalue found. Create a new one. */ uv = lj_mem_newt(L, sizeof(GCupval), GCupval); newwhite(g, uv); uv->gct = ~LJ_TUPVAL; uv->closed = 0; /* Still open. */ setmref(uv->v, slot); /* Pointing to the stack slot. */ /* NOBARRIER: The GCupval is new (marked white) and open. */ setgcrefr(uv->nextgc, *pp); /* Insert into sorted list of open upvalues. */ setgcref(*pp, obj2gco(uv)); setgcref(uv->prev, obj2gco(&g->uvhead)); /* Insert into GC list, too. */ setgcrefr(uv->next, g->uvhead.next); setgcref(uvnext(uv)->prev, obj2gco(uv)); setgcref(g->uvhead.next, obj2gco(uv)); lua_assert(uvprev(uvnext(uv)) == uv && uvnext(uvprev(uv)) == uv); return uv; }
GCudata *lj_udata_new(lua_State *L, MSize sz, GCtab *env) { GCudata *ud = lj_mem_newt(L, sizeof(GCudata) + sz, GCudata); global_State *g = G(L); newwhite(g, ud); /* Not finalized. */ ud->gct = ~LJ_TUDATA; ud->udtype = UDTYPE_USERDATA; ud->len = sz; /* NOBARRIER: The GCudata is new (marked white). */ setgcrefnull(ud->metatable); setgcref(ud->env, obj2gco(env)); /* Chain to userdata list (after main thread). */ setgcrefr(ud->nextgc, mainthread(g)->nextgc); setgcref(mainthread(g)->nextgc, obj2gco(ud)); return ud; }
/* Allocate space for copy of T. */ GCtrace * LJ_FASTCALL lj_trace_alloc(lua_State *L, GCtrace *T) { size_t sztr = ((sizeof(GCtrace)+7)&~7); size_t szins = (T->nins-T->nk)*sizeof(IRIns); size_t sz = sztr + szins + T->nsnap*sizeof(SnapShot) + T->nsnapmap*sizeof(SnapEntry); GCtrace *T2 = lj_mem_newt(L, (MSize)sz, GCtrace); char *p = (char *)T2 + sztr; T2->gct = ~LJ_TTRACE; T2->marked = 0; T2->traceno = 0; T2->ir = (IRIns *)p - T->nk; T2->nins = T->nins; T2->nk = T->nk; T2->nsnap = T->nsnap; T2->nsnapmap = T->nsnapmap; memcpy(p, T->ir + T->nk, szins); return T2; }