FFI: Fix cdata finalization.

This commit is contained in:
Mike Pall 2011-04-13 21:37:54 +02:00
parent 1fa0cc09b3
commit 31e0774a9e
7 changed files with 43 additions and 23 deletions

View File

@ -66,7 +66,8 @@ lj_ccall.o: lj_ccall.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_cconv.o: lj_cconv.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_err.h lj_errmsg.h lj_tab.h lj_ctype.h lj_gc.h lj_cdata.h lj_cconv.h
lj_cdata.o: lj_cdata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cconv.h lj_cdata.h
lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cconv.h \
lj_cdata.h
lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h
lj_clib.o: lj_clib.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_err.h lj_errmsg.h lj_tab.h lj_str.h lj_udata.h lj_ctype.h lj_cconv.h \

View File

@ -2558,7 +2558,6 @@ static void asm_cnew(ASMState *as, IRIns *ir)
lj_ctype_size(cts, typeid) : (CTSize)IR(ir->op2)->i;
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
IRRef args[2];
int gcfin = 0;
lua_assert(sz != CTSIZE_INVALID);
args[0] = ASMREF_L; /* lua_State *L */
@ -2605,15 +2604,12 @@ static void asm_cnew(ASMState *as, IRIns *ir)
} while (1);
#endif
lua_assert(sz == 4 || (sz == 8 && (LJ_64 || LJ_HASFFI)));
} else {
if (lj_ctype_meta(cts, typeid, MM_gc) != NULL)
gcfin = LJ_GC_CDATA_FIN;
}
/* Combine initialization of marked, gct and typeid. */
emit_movtomro(as, RID_ECX, RID_RET, offsetof(GCcdata, marked));
emit_gri(as, XG_ARITHi(XOg_OR), RID_ECX,
(int32_t)((~LJ_TCDATA<<8)+(typeid<<16)+gcfin));
(int32_t)((~LJ_TCDATA<<8)+(typeid<<16)));
emit_gri(as, XG_ARITHi(XOg_AND), RID_ECX, LJ_GC_WHITES);
emit_opgl(as, XO_MOVZXb, RID_ECX, gc.currentwhite);

View File

@ -10,6 +10,7 @@
#include "lj_gc.h"
#include "lj_err.h"
#include "lj_str.h"
#include "lj_tab.h"
#include "lj_ctype.h"
#include "lj_cconv.h"
#include "lj_cdata.h"
@ -74,6 +75,24 @@ void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd)
}
}
TValue * LJ_FASTCALL lj_cdata_setfin(lua_State *L, GCcdata *cd)
{
global_State *g = G(L);
GCtab *t = ctype_ctsG(g)->finalizer;
if (gcref(t->metatable)) {
/* Add cdata to finalizer table, if still enabled. */
TValue *tv, tmp;
setcdataV(L, &tmp, cd);
lj_gc_anybarriert(L, t);
tv = lj_tab_set(L, t, &tmp);
cd->marked |= LJ_GC_CDATA_FIN;
return tv;
} else {
/* Otherwise return dummy TValue. */
return &g->tmptv;
}
}
/* -- C data indexing ----------------------------------------------------- */
/* Index C data by a TValue. Return CType and pointer. */

View File

@ -62,6 +62,7 @@ LJ_FUNC GCcdata *lj_cdata_newv(CTState *cts, CTypeID id, CTSize sz,
CTSize align);
LJ_FUNC void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd);
LJ_FUNCA TValue * LJ_FASTCALL lj_cdata_setfin(lua_State *L, GCcdata *cd);
LJ_FUNC CType *lj_cdata_index(CTState *cts, GCcdata *cd, cTValue *key,
uint8_t **pp, CTInfo *qual);

View File

@ -710,20 +710,20 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
/* Handle __gc metamethod. */
fin = lj_ctype_meta(cts, id, MM_gc);
if (fin) {
RecordIndex ix;
ix.idxchain = 0;
settabV(J->L, &ix.tabv, cts->finalizer);
ix.tab = lj_ir_ktab(J, cts->finalizer);
setboolV(&ix.keyv, 0); /* The key is new. Dummy value is ok here. */
ix.key = trcd;
copyTV(J->L, &ix.valv, fin);
if (tvisfunc(fin))
ix.val = lj_ir_kfunc(J, funcV(fin));
else if (tviscdata(fin))
ix.val = lj_ir_kgc(J, obj2gco(cdataV(fin)), IRT_CDATA);
else
TRef trlo = lj_ir_call(J, IRCALL_lj_cdata_setfin, trcd);
TRef trhi = emitir(IRT(IR_ADD, IRT_P32), trlo, lj_ir_kint(J, 4));
if (LJ_BE) { TRef tmp = trlo; trlo = trhi; trhi = tmp; }
if (tvisfunc(fin)) {
emitir(IRT(IR_XSTORE, IRT_P32), trlo, lj_ir_kfunc(J, funcV(fin)));
emitir(IRTI(IR_XSTORE), trhi, lj_ir_kint(J, LJ_TFUNC));
} else if (tviscdata(fin)) {
emitir(IRT(IR_XSTORE, IRT_P32), trlo,
lj_ir_kgc(J, obj2gco(cdataV(fin)), IRT_CDATA));
emitir(IRTI(IR_XSTORE), trhi, lj_ir_kint(J, LJ_TCDATA));
} else {
lj_trace_err(J, LJ_TRERR_BADTYPE);
lj_record_idx(J, &ix);
}
J->needsnap = 1;
}
}
}

View File

@ -494,12 +494,13 @@ static void gc_finalize(lua_State *L)
setgcrefnull(g->gc.mmudata);
else
setgcrefr(gcref(g->gc.mmudata)->gch.nextgc, o->gch.nextgc);
makewhite(g, o);
#if LJ_HASFFI
if (o->gch.gct == ~LJ_TCDATA) {
TValue tmp, *tv;
setgcrefr(o->gch.nextgc, g->gc.root); /* Add cdata back to the gc list. */
/* Add cdata back to the GC list and make it white. */
setgcrefr(o->gch.nextgc, g->gc.root);
setgcref(g->gc.root, o);
o->gch.marked = curwhite(g);
/* Resolve finalizer. */
setcdataV(L, &tmp, gco2cd(o));
tv = lj_tab_set(L, ctype_ctsG(g)->finalizer, &tmp);
@ -511,9 +512,10 @@ static void gc_finalize(lua_State *L)
return;
}
#endif
/* Add userdata back to the main userdata list. */
/* Add userdata back to the main userdata list and make it white. */
setgcrefr(o->gch.nextgc, mainthread(g)->nextgc);
setgcref(mainthread(g)->nextgc, o);
makewhite(g, o);
/* Resolve the __gc metamethod. */
mo = lj_meta_fastg(g, tabref(gco2ud(o)->metatable), MM_gc);
if (mo)
@ -542,7 +544,7 @@ void lj_gc_finalize_cdata(lua_State *L)
if (!tvisnil(&node[i].val) && tviscdata(&node[i].key)) {
GCobj *o = gcV(&node[i].key);
TValue tmp;
o->gch.marked &= ~LJ_GC_CDATA_FIN;
o->gch.marked = curwhite(g);
copyTV(L, &tmp, &node[i].val);
setnilV(&node[i].val);
gc_call_finalizer(g, L, &tmp, o);

View File

@ -279,6 +279,7 @@ typedef struct CCallInfo {
_(lj_carith_modu64, ARG2_64, N, U64, CCI_NOFPRCLOBBER) \
_(lj_carith_powi64, ARG2_64, N, I64, CCI_NOFPRCLOBBER) \
_(lj_carith_powu64, ARG2_64, N, U64, CCI_NOFPRCLOBBER) \
_(lj_cdata_setfin, 2, FN, P32, CCI_L) \
_(strlen, 1, N, INTP, 0) \
_(memcpy, 3, S, PTR, 0) \
_(memset, 3, S, PTR, 0)