Bläddra i källkod

FFI: Add missing GC steps for implicit allocations.

Mike Pall 14 år sedan
förälder
incheckning
4668b229de
5 ändrade filer med 24 tillägg och 15 borttagningar
  1. 9 3
      src/lib_ffi.c
  2. 7 3
      src/lj_cconv.c
  3. 3 3
      src/lj_cconv.h
  4. 4 5
      src/lj_cdata.c
  5. 1 1
      src/lj_cdata.h

+ 9 - 3
src/lib_ffi.c

@@ -123,7 +123,8 @@ LJLIB_CF(ffi_meta___index)	LJLIB_REC(cdata_index 0)
   if (!(o+1 < L->top && tviscdata(o)))  /* Also checks for presence of key. */
     lj_err_argt(L, 1, LUA_TCDATA);
   ct = lj_cdata_index(cts, cdataV(o), o+1, &p, &qual);
-  lj_cdata_get(cts, ct, L->top-1, p);
+  if (lj_cdata_get(cts, ct, L->top-1, p))
+    lj_gc_check(L);
   return 1;
 }
 
@@ -210,6 +211,7 @@ static int ffi_arith_ptr(lua_State *L, CTState *cts, FFIArith *fa, MMS mm)
   cd = lj_cdata_new(cts, id, CTSIZE_PTR);
   *(uint8_t **)cdataptr(cd) = pp;
   setcdataV(L, L->top-1, cd);
+  lj_gc_check(L);
   return 1;
 }
 
@@ -265,6 +267,7 @@ static int ffi_arith_int64(lua_State *L, CTState *cts, FFIArith *fa, MMS mm)
     case MM_unm: *up = -u0; break;
     default: lua_assert(0); break;
     }
+    lj_gc_check(L);
     return 1;
   }
   return 0;
@@ -335,14 +338,16 @@ LJLIB_CF(ffi_meta___tostring)
     CType *ct = ctype_raw(ctype_cts(L), id);
     if (ctype_iscomplex(ct->info)) {
       setstrV(L, L->top-1, lj_ctype_repr_complex(L, cdataptr(cd), ct->size));
-      return 1;
+      goto checkgc;
     } else if (ct->size == 8 && ctype_isinteger(ct->info)) {
       setstrV(L, L->top-1, lj_ctype_repr_int64(L, *(uint64_t *)cdataptr(cd),
 					       (ct->info & CTF_UNSIGNED)));
-      return 1;
+      goto checkgc;
     }
   }
   lj_str_pushf(L, msg, strdata(lj_ctype_repr(L, id, NULL)), cdataptr(cd));
+checkgc:
+  lj_gc_check(L);
   return 1;
 }
 
@@ -402,6 +407,7 @@ LJLIB_CF(ffi_typeof)
   GCcdata *cd = lj_cdata_new(cts, CTID_CTYPEID, 4);
   *(CTypeID *)cdataptr(cd) = id;
   setcdataV(L, L->top-1, cd);
+  lj_gc_check(L);
   return 1;
 }
 

+ 7 - 3
src/lj_cconv.c

@@ -375,8 +375,8 @@ copyval:  /* Copy value. */
 /* -- C type to TValue conversion ----------------------------------------- */
 
 /* Convert C type to TValue. Caveat: expects to get the raw CType! */
-void lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid,
-		    TValue *o, uint8_t *sp)
+int lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid,
+		   TValue *o, uint8_t *sp)
 {
   CTInfo sinfo = s->info;
   lua_assert(!ctype_isenum(sinfo));
@@ -398,9 +398,11 @@ void lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid,
       setboolV(o, tmpbool);
     else
       lua_assert(tvisnum(o));
+    return 0;
   } else if (ctype_isrefarray(sinfo) || ctype_isstruct(sinfo)) {
     /* Create reference. */
     setcdataV(cts->L, o, lj_cdata_newref(cts, sp, sid));
+    return 1;  /* Need GC step. */
   } else {
     GCcdata *cd;
     CTSize sz;
@@ -411,11 +413,12 @@ void lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid,
     cd = lj_cdata_new(cts, ctype_typeid(cts, s), sz);
     setcdataV(cts->L, o, cd);
     memcpy(cdataptr(cd), sp, sz);
+    return 1;  /* Need GC step. */
   }
 }
 
 /* Convert bitfield to TValue. */
-void lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp)
+int lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp)
 {
   CTInfo info = s->info;
   CTSize pos, bsz;
@@ -445,6 +448,7 @@ void lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp)
     lua_assert(bsz == 1);
     setboolV(o, (val >> pos) & 1);
   }
+  return 0;  /* No GC step needed. */
 }
 
 /* -- TValue to C type conversion ----------------------------------------- */

+ 3 - 3
src/lj_cconv.h

@@ -52,9 +52,9 @@ static LJ_AINLINE uint32_t cconv_idx(CTInfo info)
 LJ_FUNC int lj_cconv_compatptr(CTState *cts, CType *d, CType *s, CTInfo flags);
 LJ_FUNC void lj_cconv_ct_ct(CTState *cts, CType *d, CType *s,
 			    uint8_t *dp, uint8_t *sp, CTInfo flags);
-LJ_FUNC void lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid,
-			    TValue *o, uint8_t *sp);
-LJ_FUNC void lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp);
+LJ_FUNC int lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid,
+			   TValue *o, uint8_t *sp);
+LJ_FUNC int lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp);
 LJ_FUNC void lj_cconv_ct_tv(CTState *cts, CType *d,
 			    uint8_t *dp, TValue *o, CTInfo flags);
 LJ_FUNC void lj_cconv_bf_tv(CTState *cts, CType *d, uint8_t *dp, TValue *o);

+ 4 - 5
src/lj_cdata.c

@@ -154,16 +154,15 @@ static void cdata_getconst(CTState *cts, TValue *o, CType *ct)
 }
 
 /* Get C data value and convert to TValue. */
-void lj_cdata_get(CTState *cts, CType *s, TValue *o, uint8_t *sp)
+int lj_cdata_get(CTState *cts, CType *s, TValue *o, uint8_t *sp)
 {
   CTypeID sid;
 
   if (ctype_isconstval(s->info)) {
     cdata_getconst(cts, o, s);
-    return;
+    return 0;  /* No GC step needed. */
   } else if (ctype_isbitfield(s->info)) {
-    lj_cconv_tv_bf(cts, s, o, sp);
-    return;
+    return lj_cconv_tv_bf(cts, s, o, sp);
   }
 
   /* Get child type of pointer/array/field. */
@@ -183,7 +182,7 @@ void lj_cdata_get(CTState *cts, CType *s, TValue *o, uint8_t *sp)
   while (ctype_isattrib(s->info) || ctype_isenum(s->info))
     s = ctype_child(cts, s);
 
-  lj_cconv_tv_ct(cts, s, sid, o, sp);
+  return lj_cconv_tv_ct(cts, s, sid, o, sp);
 }
 
 /* -- C data setters ------------------------------------------------------ */

+ 1 - 1
src/lj_cdata.h

@@ -62,7 +62,7 @@ LJ_FUNC void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd);
 
 LJ_FUNC CType *lj_cdata_index(CTState *cts, GCcdata *cd, cTValue *key,
 			      uint8_t **pp, CTInfo *qual);
-LJ_FUNC void lj_cdata_get(CTState *cts, CType *s, TValue *o, uint8_t *sp);
+LJ_FUNC int lj_cdata_get(CTState *cts, CType *s, TValue *o, uint8_t *sp);
 LJ_FUNC void lj_cdata_set(CTState *cts, CType *d, uint8_t *dp, TValue *o,
 			  CTInfo qual);