diff --git a/src/lib_ffi.c b/src/lib_ffi.c index 562255aa..3310b205 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c @@ -768,19 +768,11 @@ LJLIB_CF(ffi_gc) LJLIB_REC(.) GCcdata *cd = ffi_checkcdata(L, 1); TValue *fin = lj_lib_checkany(L, 2); CTState *cts = ctype_cts(L); - GCtab *t = cts->finalizer; CType *ct = ctype_raw(cts, cd->ctypeid); if (!(ctype_isptr(ct->info) || ctype_isstruct(ct->info) || ctype_isrefarray(ct->info))) lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); - if (gcref(t->metatable)) { /* Update finalizer table, if still enabled. */ - copyTV(L, lj_tab_set(L, t, L->base), fin); - lj_gc_anybarriert(L, t); - if (!tvisnil(fin)) - cd->marked |= LJ_GC_CDATA_FIN; - else - cd->marked &= ~LJ_GC_CDATA_FIN; - } + lj_cdata_setfin(L, cd, gcval(fin), itype(fin)); L->top = L->base+1; /* Pass through the cdata object. */ return 1; } diff --git a/src/lj_cdata.c b/src/lj_cdata.c index 80dcf4e5..aa3bd1a5 100644 --- a/src/lj_cdata.c +++ b/src/lj_cdata.c @@ -75,21 +75,20 @@ void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd) } } -TValue * LJ_FASTCALL lj_cdata_setfin(lua_State *L, GCcdata *cd) +void lj_cdata_setfin(lua_State *L, GCcdata *cd, GCobj *obj, uint32_t it) { - global_State *g = G(L); - GCtab *t = ctype_ctsG(g)->finalizer; + GCtab *t = ctype_ctsG(G(L))->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; + setgcV(L, tv, obj, it); + if (!tvisnil(tv)) + cd->marked |= LJ_GC_CDATA_FIN; + else + cd->marked &= ~LJ_GC_CDATA_FIN; } } diff --git a/src/lj_cdata.h b/src/lj_cdata.h index f0c23ac4..7db1ca1e 100644 --- a/src/lj_cdata.h +++ b/src/lj_cdata.h @@ -62,7 +62,8 @@ LJ_FUNC GCcdata *lj_cdata_newv(lua_State *L, 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 void lj_cdata_setfin(lua_State *L, GCcdata *cd, GCobj *obj, + uint32_t it); 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 ef6e5f82..c3b01f63 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -863,21 +863,17 @@ again: } /* Record setting a finalizer. */ -static void crec_finalizer(jit_State *J, TRef trcd, cTValue *fin) +static void crec_finalizer(jit_State *J, TRef trcd, TRef trfin, cTValue *fin) { - 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)); + if (tvisgcv(fin)) { + if (!trfin) trfin = lj_ir_kptr(J, gcval(fin)); + } else if (tvisnil(fin)) { + trfin = lj_ir_kptr(J, NULL); } else { lj_trace_err(J, LJ_TRERR_BADTYPE); } + lj_ir_call(J, IRCALL_lj_cdata_setfin, trcd, + trfin, lj_ir_kint(J, (int32_t)itype(fin))); J->needsnap = 1; } @@ -1001,7 +997,7 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) /* Handle __gc metamethod. */ fin = lj_ctype_meta(cts, id, MM_gc); if (fin) - crec_finalizer(J, trcd, fin); + crec_finalizer(J, trcd, 0, fin); } /* Record argument conversions. */ @@ -1648,7 +1644,9 @@ void LJ_FASTCALL recff_ffi_xof(jit_State *J, RecordFFData *rd) void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd) { argv2cdata(J, J->base[0], &rd->argv[0]); - crec_finalizer(J, J->base[0], &rd->argv[1]); + if (!J->base[1]) + lj_trace_err(J, LJ_TRERR_BADTYPE); + crec_finalizer(J, J->base[0], J->base[1], &rd->argv[1]); } /* -- 64 bit bit.* library functions -------------------------------------- */ diff --git a/src/lj_ircall.h b/src/lj_ircall.h index bdcfea0b..9e1fb367 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h @@ -203,7 +203,7 @@ typedef struct CCallInfo { _(FFI, lj_carith_powi64, 2, N, I64, XA2_64|CCI_NOFPRCLOBBER) \ _(FFI, lj_carith_powu64, 2, N, U64, XA2_64|CCI_NOFPRCLOBBER) \ _(FFI, lj_cdata_newv, 4, S, CDATA, CCI_L) \ - _(FFI, lj_cdata_setfin, 2, FN, P32, CCI_L) \ + _(FFI, lj_cdata_setfin, 4, S, NIL, CCI_L) \ _(FFI, strlen, 1, L, INTP, 0) \ _(FFI, memcpy, 3, S, PTR, 0) \ _(FFI, memset, 3, S, PTR, 0) \