/* Handle ctype __gc metamethod. Use the fast lookup here. */
cTValue *tv = lj_tab_getinth(cts->miscmap, -(int32_t)id);
if (tv && tvistab(tv) && (tv = lj_meta_fast(L, tabV(tv), MM_gc))) {
- GCtab *t = cts->finalizer;
+ GCtab *t = tabref(G(L)->gcroot[GCROOT_FFI_FIN]);
if (gcref(t->metatable)) {
/* Add to finalizer table, if still enabled. */
copyTV(L, lj_tab_set(L, t, o-1), tv);
return 1;
}
-LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to miscmap table. */
+LJLIB_PUSH(top-7) LJLIB_SET(!) /* Store reference to miscmap table. */
LJLIB_CF(ffi_metatype)
{
return 1;
}
-LJLIB_PUSH(top-7) LJLIB_SET(!) /* Store reference to finalizer table. */
-
LJLIB_CF(ffi_gc) LJLIB_REC(.)
{
GCcdata *cd = ffi_checkcdata(L, 1);
/* ------------------------------------------------------------------------ */
-/* Create special weak-keyed finalizer table. */
-static GCtab *ffi_finalizer(lua_State *L)
-{
- /* NOBARRIER: The table is new (marked white). */
- GCtab *t = lj_tab_new(L, 0, 1);
- settabV(L, L->top++, t);
- setgcref(t->metatable, obj2gco(t));
- setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")),
- lj_str_newlit(L, "k"));
- t->nomm = (uint8_t)(~(1u<<MM_mode));
- return t;
-}
-
/* Register FFI module as loaded. */
static void ffi_register_module(lua_State *L)
{
{
CTState *cts = lj_ctype_init(L);
settabV(L, L->top++, (cts->miscmap = lj_tab_new(L, 0, 1)));
- cts->finalizer = ffi_finalizer(L);
LJ_LIB_REG(L, NULL, ffi_meta);
/* NOBARRIER: basemt is a GC root. */
setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1)));
void lj_cdata_setfin(lua_State *L, GCcdata *cd, GCobj *obj, uint32_t it)
{
- GCtab *t = ctype_ctsG(G(L))->finalizer;
+ GCtab *t = tabref(G(L)->gcroot[GCROOT_FFI_FIN]);
if (gcref(t->metatable)) {
/* Add cdata to finalizer table, if still enabled. */
TValue *tv, tmp;
return cts;
}
+/* Create special weak-keyed finalizer table. */
+void lj_ctype_initfin(lua_State *L)
+{
+ /* NOBARRIER: The table is new (marked white). */
+ GCtab *t = lj_tab_new(L, 0, 1);
+ setgcref(t->metatable, obj2gco(t));
+ setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")),
+ lj_str_newlit(L, "k"));
+ t->nomm = (uint8_t)(~(1u<<MM_mode));
+ setgcref(G(L)->gcroot[GCROOT_FFI_FIN], obj2gco(t));
+}
+
/* Free C type table and state. */
void lj_ctype_freestate(global_State *g)
{
MSize sizetab; /* Size of C type table. */
lua_State *L; /* Lua state (needed for errors and allocations). */
global_State *g; /* Global state. */
- GCtab *finalizer; /* Map of cdata to finalizer. */
GCtab *miscmap; /* Map of -CTypeID to metatable and cb slot to func. */
CCallback cb; /* Temporary callback state. */
CTypeID1 hash[CTHASH_SIZE]; /* Hash anchors for C type table. */
LJ_FUNC GCstr *lj_ctype_repr_int64(lua_State *L, uint64_t n, int isunsigned);
LJ_FUNC GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size);
LJ_FUNC CTState *lj_ctype_init(lua_State *L);
+LJ_FUNC void lj_ctype_initfin(lua_State *L);
LJ_FUNC void lj_ctype_freestate(global_State *g);
#endif
gc_markobj(g, tabref(mainthread(g)->env));
gc_marktv(g, &g->registrytv);
gc_mark_gcroot(g);
-#if LJ_HASFFI
- if (ctype_ctsG(g)) gc_markobj(g, ctype_ctsG(g)->finalizer);
-#endif
g->gc.state = GCSpropagate;
}
}
if (weak) { /* Weak tables are cleared in the atomic phase. */
#if LJ_HASFFI
- CTState *cts = ctype_ctsG(g);
- if (cts && cts->finalizer == t) {
+ if (gcref(g->gcroot[GCROOT_FFI_FIN]) == obj2gco(t)) {
weak = (int)(~0u & ~LJ_GC_WEAKVAL);
} else
#endif
o->gch.marked &= (uint8_t)~LJ_GC_CDATA_FIN;
/* Resolve finalizer. */
setcdataV(L, &tmp, gco2cd(o));
- tv = lj_tab_set(L, ctype_ctsG(g)->finalizer, &tmp);
+ tv = lj_tab_set(L, tabref(g->gcroot[GCROOT_FFI_FIN]), &tmp);
if (!tvisnil(tv)) {
g->gc.nocdatafin = 0;
copyTV(L, &tmp, tv);
void lj_gc_finalize_cdata(lua_State *L)
{
global_State *g = G(L);
- CTState *cts = ctype_ctsG(g);
- if (cts) {
- GCtab *t = cts->finalizer;
- Node *node = noderef(t->node);
- ptrdiff_t i;
- setgcrefnull(t->metatable); /* Mark finalizer table as disabled. */
- for (i = (ptrdiff_t)t->hmask; i >= 0; i--)
- if (!tvisnil(&node[i].val) && tviscdata(&node[i].key)) {
- GCobj *o = gcV(&node[i].key);
- TValue tmp;
- makewhite(g, o);
- o->gch.marked &= (uint8_t)~LJ_GC_CDATA_FIN;
- copyTV(L, &tmp, &node[i].val);
- setnilV(&node[i].val);
- gc_call_finalizer(g, L, &tmp, o);
- }
- }
+ GCtab *t = tabref(g->gcroot[GCROOT_FFI_FIN]);
+ Node *node = noderef(t->node);
+ ptrdiff_t i;
+ setgcrefnull(t->metatable); /* Mark finalizer table as disabled. */
+ for (i = (ptrdiff_t)t->hmask; i >= 0; i--)
+ if (!tvisnil(&node[i].val) && tviscdata(&node[i].key)) {
+ GCobj *o = gcV(&node[i].key);
+ TValue tmp;
+ makewhite(g, o);
+ o->gch.marked &= (uint8_t)~LJ_GC_CDATA_FIN;
+ copyTV(L, &tmp, &node[i].val);
+ setnilV(&node[i].val);
+ gc_call_finalizer(g, L, &tmp, o);
+ }
}
#endif
return GCFINALIZECOST;
}
#if LJ_HASFFI
- if (!g->gc.nocdatafin) lj_tab_rehash(L, ctype_ctsG(g)->finalizer);
+ if (!g->gc.nocdatafin) lj_tab_rehash(L, tabref(g->gcroot[GCROOT_FFI_FIN]));
#endif
g->gc.state = GCSpause; /* End of GC cycle. */
g->gc.debt = 0;
GCROOT_BASEMT_NUM = GCROOT_BASEMT + ~LJ_TNUMX,
GCROOT_IO_INPUT, /* Userdata for default I/O input file. */
GCROOT_IO_OUTPUT, /* Userdata for default I/O output file. */
+#if LJ_HASFFI
+ GCROOT_FFI_FIN, /* FFI finalizer table. */
+#endif
GCROOT_MAX
} GCRootID;
lj_lex_init(L);
fixstring(lj_err_str(L, LJ_ERR_ERRMEM)); /* Preallocate memory error msg. */
g->gc.threshold = 4*g->gc.total;
+#if LJ_HASFFI
+ lj_ctype_initfin(L);
+#endif
lj_trace_initstate(g);
lj_err_verify();
return NULL;