Inline-Lua
view release on metacpan or search on metacpan
ffi/target/release/build/mlua-sys-6a99a2ae50f12319/out/luajit-build/build/src/lj_gc.c view on Meta::CPAN
gc_traverse_trace(g, T);
return ((sizeof(GCtrace)+7)&~7) + (T->nins-T->nk)*sizeof(IRIns) +
T->nsnap*sizeof(SnapShot) + T->nsnapmap*sizeof(SnapEntry);
#else
lj_assertG(0, "bad GC type %d", gct);
return 0;
#endif
}
}
/* Propagate all gray objects. */
static size_t gc_propagate_gray(global_State *g)
{
size_t m = 0;
while (gcref(g->gc.gray) != NULL)
m += propagatemark(g);
return m;
}
/* -- Sweep phase --------------------------------------------------------- */
/* Type of GC free functions. */
typedef void (LJ_FASTCALL *GCFreeFunc)(global_State *g, GCobj *o);
/* GC free functions for LJ_TSTR .. LJ_TUDATA. ORDER LJ_T */
static const GCFreeFunc gc_freefunc[] = {
(GCFreeFunc)lj_str_free,
(GCFreeFunc)lj_func_freeuv,
(GCFreeFunc)lj_state_free,
(GCFreeFunc)lj_func_freeproto,
(GCFreeFunc)lj_func_free,
#if LJ_HASJIT
(GCFreeFunc)lj_trace_free,
#else
(GCFreeFunc)0,
#endif
#if LJ_HASFFI
(GCFreeFunc)lj_cdata_free,
#else
(GCFreeFunc)0,
#endif
(GCFreeFunc)lj_tab_free,
(GCFreeFunc)lj_udata_free
};
/* Full sweep of a GC list. */
#define gc_fullsweep(g, p) gc_sweep(g, (p), ~(uint32_t)0)
/* Partial sweep of a GC list. */
static GCRef *gc_sweep(global_State *g, GCRef *p, uint32_t lim)
{
/* Mask with other white and LJ_GC_FIXED. Or LJ_GC_SFIXED on shutdown. */
int ow = otherwhite(g);
GCobj *o;
while ((o = gcref(*p)) != NULL && lim-- > 0) {
if (o->gch.gct == ~LJ_TTHREAD) /* Need to sweep open upvalues, too. */
gc_fullsweep(g, &gco2th(o)->openupval);
if (((o->gch.marked ^ LJ_GC_WHITES) & ow)) { /* Black or current white? */
lj_assertG(!isdead(g, o) || (o->gch.marked & LJ_GC_FIXED),
"sweep of undead object");
makewhite(g, o); /* Value is alive, change to the current white. */
p = &o->gch.nextgc;
} else { /* Otherwise value is dead, free it. */
lj_assertG(isdead(g, o) || ow == LJ_GC_SFIXED,
"sweep of unlive object");
setgcrefr(*p, o->gch.nextgc);
if (o == gcref(g->gc.root))
setgcrefr(g->gc.root, o->gch.nextgc); /* Adjust list anchor. */
gc_freefunc[o->gch.gct - ~LJ_TSTR](g, o);
}
}
return p;
}
/* Sweep one string interning table chain. Preserves hashalg bit. */
static void gc_sweepstr(global_State *g, GCRef *chain)
{
/* Mask with other white and LJ_GC_FIXED. Or LJ_GC_SFIXED on shutdown. */
int ow = otherwhite(g);
uintptr_t u = gcrefu(*chain);
GCRef q;
GCRef *p = &q;
GCobj *o;
setgcrefp(q, (u & ~(uintptr_t)1));
while ((o = gcref(*p)) != NULL) {
if (((o->gch.marked ^ LJ_GC_WHITES) & ow)) { /* Black or current white? */
lj_assertG(!isdead(g, o) || (o->gch.marked & LJ_GC_FIXED),
"sweep of undead string");
makewhite(g, o); /* String is alive, change to the current white. */
p = &o->gch.nextgc;
} else { /* Otherwise string is dead, free it. */
lj_assertG(isdead(g, o) || ow == LJ_GC_SFIXED,
"sweep of unlive string");
setgcrefr(*p, o->gch.nextgc);
lj_str_free(g, gco2str(o));
}
}
setgcrefp(*chain, (gcrefu(q) | (u & 1)));
}
/* Check whether we can clear a key or a value slot from a table. */
static int gc_mayclear(cTValue *o, int val)
{
if (tvisgcv(o)) { /* Only collectable objects can be weak references. */
if (tvisstr(o)) { /* But strings cannot be used as weak references. */
gc_mark_str(strV(o)); /* And need to be marked. */
return 0;
}
if (iswhite(gcV(o)))
return 1; /* Object is about to be collected. */
if (tvisudata(o) && val && isfinalized(udataV(o)))
return 1; /* Finalized userdata is dropped only from values. */
}
return 0; /* Cannot clear. */
}
/* Clear collected entries from weak tables. */
static void gc_clearweak(global_State *g, GCobj *o)
{
UNUSED(g);
while (o) {
GCtab *t = gco2tab(o);
lj_assertG((t->marked & LJ_GC_WEAK), "clear of non-weak table");
if ((t->marked & LJ_GC_WEAKVAL)) {
MSize i, asize = t->asize;
for (i = 0; i < asize; i++) {
/* Clear array slot when value is about to be collected. */
TValue *tv = arrayslot(t, i);
if (gc_mayclear(tv, 1))
setnilV(tv);
}
}
if (t->hmask > 0) {
Node *node = noderef(t->node);
MSize i, hmask = t->hmask;
for (i = 0; i <= hmask; i++) {
Node *n = &node[i];
/* Clear hash slot when key or value is about to be collected. */
if (!tvisnil(&n->val) && (gc_mayclear(&n->key, 0) ||
gc_mayclear(&n->val, 1)))
setnilV(&n->val);
}
}
o = gcref(t->gclist);
}
}
/* Call a userdata or cdata finalizer. */
static void gc_call_finalizer(global_State *g, lua_State *L,
( run in 0.650 second using v1.01-cache-2.11-cpan-5a3173703d6 )