Przeglądaj źródła

FFI: Fix cdata finalization.

Mike Pall 14 lat temu
rodzic
commit
31e0774a9e
7 zmienionych plików z 43 dodań i 23 usunięć
  1. 2 1
      src/Makefile.dep
  2. 1 5
      src/lj_asm.c
  3. 19 0
      src/lj_cdata.c
  4. 1 0
      src/lj_cdata.h
  5. 13 13
      src/lj_crecord.c
  6. 6 4
      src/lj_gc.c
  7. 1 0
      src/lj_ir.h

+ 2 - 1
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 \

+ 1 - 5
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);
 

+ 19 - 0
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. */

+ 1 - 0
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);

+ 13 - 13
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;
     }
   }
 }

+ 6 - 4
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);

+ 1 - 0
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)