FFI: Refactor ffi.gc()/__gc. Compile ffi.gc(cdata, nil), too.

This commit is contained in:
Mike Pall 2013-05-24 17:44:55 +02:00
parent 4c1f9dd0f7
commit 992f7d4b71
5 changed files with 22 additions and 32 deletions

View File

@ -768,19 +768,11 @@ LJLIB_CF(ffi_gc) LJLIB_REC(.)
GCcdata *cd = ffi_checkcdata(L, 1); GCcdata *cd = ffi_checkcdata(L, 1);
TValue *fin = lj_lib_checkany(L, 2); TValue *fin = lj_lib_checkany(L, 2);
CTState *cts = ctype_cts(L); CTState *cts = ctype_cts(L);
GCtab *t = cts->finalizer;
CType *ct = ctype_raw(cts, cd->ctypeid); CType *ct = ctype_raw(cts, cd->ctypeid);
if (!(ctype_isptr(ct->info) || ctype_isstruct(ct->info) || if (!(ctype_isptr(ct->info) || ctype_isstruct(ct->info) ||
ctype_isrefarray(ct->info))) ctype_isrefarray(ct->info)))
lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE);
if (gcref(t->metatable)) { /* Update finalizer table, if still enabled. */ lj_cdata_setfin(L, cd, gcval(fin), itype(fin));
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;
}
L->top = L->base+1; /* Pass through the cdata object. */ L->top = L->base+1; /* Pass through the cdata object. */
return 1; return 1;
} }

View File

@ -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(L))->finalizer;
GCtab *t = ctype_ctsG(g)->finalizer;
if (gcref(t->metatable)) { if (gcref(t->metatable)) {
/* Add cdata to finalizer table, if still enabled. */ /* Add cdata to finalizer table, if still enabled. */
TValue *tv, tmp; TValue *tv, tmp;
setcdataV(L, &tmp, cd); setcdataV(L, &tmp, cd);
lj_gc_anybarriert(L, t); lj_gc_anybarriert(L, t);
tv = lj_tab_set(L, t, &tmp); tv = lj_tab_set(L, t, &tmp);
setgcV(L, tv, obj, it);
if (!tvisnil(tv))
cd->marked |= LJ_GC_CDATA_FIN; cd->marked |= LJ_GC_CDATA_FIN;
return tv; else
} else { cd->marked &= ~LJ_GC_CDATA_FIN;
/* Otherwise return dummy TValue. */
return &g->tmptv;
} }
} }

View File

@ -62,7 +62,8 @@ LJ_FUNC GCcdata *lj_cdata_newv(lua_State *L, 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 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, LJ_FUNC CType *lj_cdata_index(CTState *cts, GCcdata *cd, cTValue *key,
uint8_t **pp, CTInfo *qual); uint8_t **pp, CTInfo *qual);

View File

@ -863,21 +863,17 @@ again:
} }
/* Record setting a finalizer. */ /* 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); if (tvisgcv(fin)) {
TRef trhi = emitir(IRT(IR_ADD, IRT_P32), trlo, lj_ir_kint(J, 4)); if (!trfin) trfin = lj_ir_kptr(J, gcval(fin));
if (LJ_BE) { TRef tmp = trlo; trlo = trhi; trhi = tmp; } } else if (tvisnil(fin)) {
if (tvisfunc(fin)) { trfin = lj_ir_kptr(J, NULL);
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 { } else {
lj_trace_err(J, LJ_TRERR_BADTYPE); 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; J->needsnap = 1;
} }
@ -1001,7 +997,7 @@ 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)
crec_finalizer(J, trcd, fin); crec_finalizer(J, trcd, 0, fin);
} }
/* Record argument conversions. */ /* 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) void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd)
{ {
argv2cdata(J, J->base[0], &rd->argv[0]); 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 -------------------------------------- */ /* -- 64 bit bit.* library functions -------------------------------------- */

View File

@ -203,7 +203,7 @@ typedef struct CCallInfo {
_(FFI, lj_carith_powi64, 2, N, I64, XA2_64|CCI_NOFPRCLOBBER) \ _(FFI, lj_carith_powi64, 2, N, I64, XA2_64|CCI_NOFPRCLOBBER) \
_(FFI, lj_carith_powu64, 2, N, U64, 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_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, strlen, 1, L, INTP, 0) \
_(FFI, memcpy, 3, S, PTR, 0) \ _(FFI, memcpy, 3, S, PTR, 0) \
_(FFI, memset, 3, S, PTR, 0) \ _(FFI, memset, 3, S, PTR, 0) \