mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 23:24:09 +00:00
FFI: Fix cdata finalization.
This commit is contained in:
parent
1fa0cc09b3
commit
31e0774a9e
@ -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_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_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_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_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_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 \
|
lj_err.h lj_errmsg.h lj_tab.h lj_str.h lj_udata.h lj_ctype.h lj_cconv.h \
|
||||||
|
@ -2558,7 +2558,6 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
lj_ctype_size(cts, typeid) : (CTSize)IR(ir->op2)->i;
|
lj_ctype_size(cts, typeid) : (CTSize)IR(ir->op2)->i;
|
||||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
|
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
|
||||||
IRRef args[2];
|
IRRef args[2];
|
||||||
int gcfin = 0;
|
|
||||||
lua_assert(sz != CTSIZE_INVALID);
|
lua_assert(sz != CTSIZE_INVALID);
|
||||||
|
|
||||||
args[0] = ASMREF_L; /* lua_State *L */
|
args[0] = ASMREF_L; /* lua_State *L */
|
||||||
@ -2605,15 +2604,12 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
} while (1);
|
} while (1);
|
||||||
#endif
|
#endif
|
||||||
lua_assert(sz == 4 || (sz == 8 && (LJ_64 || LJ_HASFFI)));
|
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. */
|
/* Combine initialization of marked, gct and typeid. */
|
||||||
emit_movtomro(as, RID_ECX, RID_RET, offsetof(GCcdata, marked));
|
emit_movtomro(as, RID_ECX, RID_RET, offsetof(GCcdata, marked));
|
||||||
emit_gri(as, XG_ARITHi(XOg_OR), RID_ECX,
|
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_gri(as, XG_ARITHi(XOg_AND), RID_ECX, LJ_GC_WHITES);
|
||||||
emit_opgl(as, XO_MOVZXb, RID_ECX, gc.currentwhite);
|
emit_opgl(as, XO_MOVZXb, RID_ECX, gc.currentwhite);
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "lj_gc.h"
|
#include "lj_gc.h"
|
||||||
#include "lj_err.h"
|
#include "lj_err.h"
|
||||||
#include "lj_str.h"
|
#include "lj_str.h"
|
||||||
|
#include "lj_tab.h"
|
||||||
#include "lj_ctype.h"
|
#include "lj_ctype.h"
|
||||||
#include "lj_cconv.h"
|
#include "lj_cconv.h"
|
||||||
#include "lj_cdata.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 ----------------------------------------------------- */
|
/* -- C data indexing ----------------------------------------------------- */
|
||||||
|
|
||||||
/* Index C data by a TValue. Return CType and pointer. */
|
/* Index C data by a TValue. Return CType and pointer. */
|
||||||
|
@ -62,6 +62,7 @@ LJ_FUNC GCcdata *lj_cdata_newv(CTState *cts, CTypeID id, CTSize sz,
|
|||||||
CTSize align);
|
CTSize align);
|
||||||
|
|
||||||
LJ_FUNC void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd);
|
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,
|
LJ_FUNC CType *lj_cdata_index(CTState *cts, GCcdata *cd, cTValue *key,
|
||||||
uint8_t **pp, CTInfo *qual);
|
uint8_t **pp, CTInfo *qual);
|
||||||
|
@ -710,20 +710,20 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
|
|||||||
/* Handle __gc metamethod. */
|
/* Handle __gc metamethod. */
|
||||||
fin = lj_ctype_meta(cts, id, MM_gc);
|
fin = lj_ctype_meta(cts, id, MM_gc);
|
||||||
if (fin) {
|
if (fin) {
|
||||||
RecordIndex ix;
|
TRef trlo = lj_ir_call(J, IRCALL_lj_cdata_setfin, trcd);
|
||||||
ix.idxchain = 0;
|
TRef trhi = emitir(IRT(IR_ADD, IRT_P32), trlo, lj_ir_kint(J, 4));
|
||||||
settabV(J->L, &ix.tabv, cts->finalizer);
|
if (LJ_BE) { TRef tmp = trlo; trlo = trhi; trhi = tmp; }
|
||||||
ix.tab = lj_ir_ktab(J, cts->finalizer);
|
if (tvisfunc(fin)) {
|
||||||
setboolV(&ix.keyv, 0); /* The key is new. Dummy value is ok here. */
|
emitir(IRT(IR_XSTORE, IRT_P32), trlo, lj_ir_kfunc(J, funcV(fin)));
|
||||||
ix.key = trcd;
|
emitir(IRTI(IR_XSTORE), trhi, lj_ir_kint(J, LJ_TFUNC));
|
||||||
copyTV(J->L, &ix.valv, fin);
|
} else if (tviscdata(fin)) {
|
||||||
if (tvisfunc(fin))
|
emitir(IRT(IR_XSTORE, IRT_P32), trlo,
|
||||||
ix.val = lj_ir_kfunc(J, funcV(fin));
|
lj_ir_kgc(J, obj2gco(cdataV(fin)), IRT_CDATA));
|
||||||
else if (tviscdata(fin))
|
emitir(IRTI(IR_XSTORE), trhi, lj_ir_kint(J, LJ_TCDATA));
|
||||||
ix.val = lj_ir_kgc(J, obj2gco(cdataV(fin)), IRT_CDATA);
|
} else {
|
||||||
else
|
|
||||||
lj_trace_err(J, LJ_TRERR_BADTYPE);
|
lj_trace_err(J, LJ_TRERR_BADTYPE);
|
||||||
lj_record_idx(J, &ix);
|
}
|
||||||
|
J->needsnap = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
src/lj_gc.c
10
src/lj_gc.c
@ -494,12 +494,13 @@ static void gc_finalize(lua_State *L)
|
|||||||
setgcrefnull(g->gc.mmudata);
|
setgcrefnull(g->gc.mmudata);
|
||||||
else
|
else
|
||||||
setgcrefr(gcref(g->gc.mmudata)->gch.nextgc, o->gch.nextgc);
|
setgcrefr(gcref(g->gc.mmudata)->gch.nextgc, o->gch.nextgc);
|
||||||
makewhite(g, o);
|
|
||||||
#if LJ_HASFFI
|
#if LJ_HASFFI
|
||||||
if (o->gch.gct == ~LJ_TCDATA) {
|
if (o->gch.gct == ~LJ_TCDATA) {
|
||||||
TValue tmp, *tv;
|
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);
|
setgcref(g->gc.root, o);
|
||||||
|
o->gch.marked = curwhite(g);
|
||||||
/* Resolve finalizer. */
|
/* Resolve finalizer. */
|
||||||
setcdataV(L, &tmp, gco2cd(o));
|
setcdataV(L, &tmp, gco2cd(o));
|
||||||
tv = lj_tab_set(L, ctype_ctsG(g)->finalizer, &tmp);
|
tv = lj_tab_set(L, ctype_ctsG(g)->finalizer, &tmp);
|
||||||
@ -511,9 +512,10 @@ static void gc_finalize(lua_State *L)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
setgcrefr(o->gch.nextgc, mainthread(g)->nextgc);
|
||||||
setgcref(mainthread(g)->nextgc, o);
|
setgcref(mainthread(g)->nextgc, o);
|
||||||
|
makewhite(g, o);
|
||||||
/* Resolve the __gc metamethod. */
|
/* Resolve the __gc metamethod. */
|
||||||
mo = lj_meta_fastg(g, tabref(gco2ud(o)->metatable), MM_gc);
|
mo = lj_meta_fastg(g, tabref(gco2ud(o)->metatable), MM_gc);
|
||||||
if (mo)
|
if (mo)
|
||||||
@ -542,7 +544,7 @@ void lj_gc_finalize_cdata(lua_State *L)
|
|||||||
if (!tvisnil(&node[i].val) && tviscdata(&node[i].key)) {
|
if (!tvisnil(&node[i].val) && tviscdata(&node[i].key)) {
|
||||||
GCobj *o = gcV(&node[i].key);
|
GCobj *o = gcV(&node[i].key);
|
||||||
TValue tmp;
|
TValue tmp;
|
||||||
o->gch.marked &= ~LJ_GC_CDATA_FIN;
|
o->gch.marked = curwhite(g);
|
||||||
copyTV(L, &tmp, &node[i].val);
|
copyTV(L, &tmp, &node[i].val);
|
||||||
setnilV(&node[i].val);
|
setnilV(&node[i].val);
|
||||||
gc_call_finalizer(g, L, &tmp, o);
|
gc_call_finalizer(g, L, &tmp, o);
|
||||||
|
@ -279,6 +279,7 @@ typedef struct CCallInfo {
|
|||||||
_(lj_carith_modu64, ARG2_64, N, U64, CCI_NOFPRCLOBBER) \
|
_(lj_carith_modu64, ARG2_64, N, U64, CCI_NOFPRCLOBBER) \
|
||||||
_(lj_carith_powi64, ARG2_64, N, I64, CCI_NOFPRCLOBBER) \
|
_(lj_carith_powi64, ARG2_64, N, I64, CCI_NOFPRCLOBBER) \
|
||||||
_(lj_carith_powu64, ARG2_64, N, U64, CCI_NOFPRCLOBBER) \
|
_(lj_carith_powu64, ARG2_64, N, U64, CCI_NOFPRCLOBBER) \
|
||||||
|
_(lj_cdata_setfin, 2, FN, P32, CCI_L) \
|
||||||
_(strlen, 1, N, INTP, 0) \
|
_(strlen, 1, N, INTP, 0) \
|
||||||
_(memcpy, 3, S, PTR, 0) \
|
_(memcpy, 3, S, PTR, 0) \
|
||||||
_(memset, 3, S, PTR, 0)
|
_(memset, 3, S, PTR, 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user