瀏覽代碼

FFI: Record ffi.copy() and ffi.fill().

Mike Pall 14 年之前
父節點
當前提交
7a37b93f1b
共有 5 個文件被更改,包括 57 次插入19 次删除
  1. 4 4
      doc/ext_ffi_api.html
  2. 12 14
      src/lib_ffi.c
  3. 34 0
      src/lj_crecord.c
  4. 4 0
      src/lj_crecord.h
  5. 3 1
      src/lj_ir.h

+ 4 - 4
doc/ext_ffi_api.html

@@ -312,13 +312,13 @@ is converted to a <tt>"const void&nbsp;*"</tt>.
 </p>
 <p>
 In the first syntax, <tt>len</tt> gives the number of bytes to copy.
-In case <tt>src</tt> is a Lua string, the maximum copy length is the
-number of bytes of the string plus a zero-terminator. Caveat: the
-copied data may not be zero-terminated if <tt>len&nbsp;&le;&nbsp;#src</tt>.
+Caveat: if <tt>src</tt> is a Lua string, then <tt>len</tt> must not
+exceed <tt>#src+1</tt>.
 </p>
 <p>
 In the second syntax, the source of the copy must be a Lua string. All
-bytes of the string plus a zero-terminator are copied to <tt>dst</tt>.
+bytes of the string <em>plus a zero-terminator</em> are copied to
+<tt>dst</tt> (i.e. <tt>#src+1</tt> bytes).
 </p>
 <p>
 Performance notice: <tt>ffi.copy()</tt> may be used as a faster

+ 12 - 14
src/lib_ffi.c

@@ -455,29 +455,27 @@ LJLIB_CF(ffi_string)	LJLIB_REC(.)
   return 1;
 }
 
-LJLIB_CF(ffi_copy)
+LJLIB_CF(ffi_copy)	LJLIB_REC(.)
 {
   void *dp = ffi_checkptr(L, 1, CTID_P_VOID);
   void *sp = ffi_checkptr(L, 2, CTID_P_CVOID);
   TValue *o = L->base+1;
-  CTSize sz;
-  if (tvisstr(o) && o+1 >= L->top) {
-    sz = strV(o)->len+1;  /* Copy Lua string including trailing '\0'. */
-  } else {
-    sz = (CTSize)ffi_checkint(L, 3);
-    if (tvisstr(o) && sz > strV(o)->len+1)
-      sz = strV(o)->len+1;  /* Max. copy length is string length. */
-  }
-  memcpy(dp, sp, sz);
+  CTSize len;
+  if (tvisstr(o) && o+1 >= L->top)
+    len = strV(o)->len+1;  /* Copy Lua string including trailing '\0'. */
+  else
+    len = (CTSize)ffi_checkint(L, 3);
+  memcpy(dp, sp, len);
   return 0;
 }
 
-LJLIB_CF(ffi_fill)
+LJLIB_CF(ffi_fill)	LJLIB_REC(.)
 {
   void *dp = ffi_checkptr(L, 1, CTID_P_VOID);
-  CTSize sz = (CTSize)ffi_checkint(L, 2);
-  int32_t fill = lj_lib_optint(L, 3, 0);
-  memset(dp, fill, sz);
+  CTSize len = (CTSize)ffi_checkint(L, 2);
+  int32_t fill = 0;
+  if (L->base+2 < L->top && !tvisnil(L->base+2)) fill = ffi_checkint(L, 3);
+  memset(dp, fill, len);
   return 0;
 }
 

+ 34 - 0
src/lj_crecord.c

@@ -974,6 +974,40 @@ void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd)
   }  /* else: interpreter will throw. */
 }
 
+void LJ_FASTCALL recff_ffi_copy(jit_State *J, RecordFFData *rd)
+{
+  CTState *cts = ctype_ctsG(J2G(J));
+  TRef trdst = J->base[0], trsrc = J->base[1], trlen = J->base[2];
+  if (trdst && trsrc && (trlen || tref_isstr(trsrc))) {
+    trdst = crec_ct_tv(J, ctype_get(cts, CTID_P_VOID), 0, trdst, &rd->argv[0]);
+    trsrc = crec_ct_tv(J, ctype_get(cts, CTID_P_CVOID), 0, trsrc, &rd->argv[1]);
+    if (trlen) {
+      trlen = crec_toint(J, cts, trlen, &rd->argv[2]);
+    } else {
+      trlen = emitir(IRTI(IR_FLOAD), trsrc, IRFL_STR_LEN);
+      trlen = emitir(IRTI(IR_ADD), trlen, lj_ir_kint(J, 1));
+    }
+    lj_ir_call(J, IRCALL_memcpy, trdst, trsrc, trlen);
+    emitir(IRT(IR_XBAR, IRT_NIL), 0, 0);
+  }  /* else: interpreter will throw. */
+}
+
+void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd)
+{
+  CTState *cts = ctype_ctsG(J2G(J));
+  TRef tr = J->base[0], trlen = J->base[1], trfill = J->base[2];
+  if (tr && trlen) {
+    tr = crec_ct_tv(J, ctype_get(cts, CTID_P_VOID), 0, tr, &rd->argv[0]);
+    trlen = crec_toint(J, cts, trlen, &rd->argv[1]);
+    if (trfill)
+      trfill = crec_toint(J, cts, trfill, &rd->argv[2]);
+    else
+      trfill = lj_ir_kint(J, 0);
+    lj_ir_call(J, IRCALL_memset, tr, trfill, trlen);
+    emitir(IRT(IR_XBAR, IRT_NIL), 0, 0);
+  }  /* else: interpreter will throw. */
+}
+
 /* -- Miscellaneous library functions ------------------------------------- */
 
 void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd)

+ 4 - 0
src/lj_crecord.h

@@ -17,6 +17,8 @@ LJ_FUNC void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd);
 LJ_FUNC void LJ_FASTCALL recff_clib_index(jit_State *J, RecordFFData *rd);
 LJ_FUNC void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd);
 LJ_FUNC void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd);
+LJ_FUNC void LJ_FASTCALL recff_ffi_copy(jit_State *J, RecordFFData *rd);
+LJ_FUNC void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd);
 LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd);
 #else
 #define recff_cdata_index	recff_nyi
@@ -25,6 +27,8 @@ LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd);
 #define recff_clib_index	recff_nyi
 #define recff_ffi_new		recff_nyi
 #define recff_ffi_string	recff_nyi
+#define recff_ffi_copy		recff_nyi
+#define recff_ffi_fill		recff_nyi
 #endif
 
 #endif

+ 3 - 1
src/lj_ir.h

@@ -276,7 +276,9 @@ 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) \
-  _(strlen,		1,         N, INT, 0)
+  _(strlen,		1,         N, INTP, 0) \
+  _(memcpy,		3,         S, PTR, 0) \
+  _(memset,		3,         S, PTR, 0)
 #else
 #define IRCALLDEF_FFI(_)
 #endif