diff --git a/src/Makefile.dep b/src/Makefile.dep index c06060ce..4f5317b9 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -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 \ diff --git a/src/lj_asm.c b/src/lj_asm.c index 8e7c98ee..a69f4461 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c @@ -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); diff --git a/src/lj_cdata.c b/src/lj_cdata.c index 53605e7e..d01cf62a 100644 --- a/src/lj_cdata.c +++ b/src/lj_cdata.c @@ -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. */ diff --git a/src/lj_cdata.h b/src/lj_cdata.h index 74cdab42..feb1bbf2 100644 --- a/src/lj_cdata.h +++ b/src/lj_cdata.h @@ -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); diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 04c962d5..83c57063 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -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; } } } diff --git a/src/lj_gc.c b/src/lj_gc.c index aba19d3f..7999e31f 100644 --- a/src/lj_gc.c +++ b/src/lj_gc.c @@ -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); diff --git a/src/lj_ir.h b/src/lj_ir.h index c46bbbe0..5659ba73 100644 --- a/src/lj_ir.h +++ b/src/lj_ir.h @@ -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)