aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/ext_ffi_semantics.html12
-rw-r--r--src/lib_ffi.c41
-rw-r--r--src/lj_crecord.c44
-rw-r--r--src/lj_obj.h8
4 files changed, 63 insertions, 42 deletions
diff --git a/doc/ext_ffi_semantics.html b/doc/ext_ffi_semantics.html
index 4b498fbe..d0613aed 100644
--- a/doc/ext_ffi_semantics.html
+++ b/doc/ext_ffi_semantics.html
@@ -599,8 +599,9 @@ C type pointed to by the reference.
599</p> 599</p>
600<p> 600<p>
601The pre-defined operations are always tried first before deferring to a 601The pre-defined operations are always tried first before deferring to a
602metamethod or index table (if any) for the corresponding ctype. An error 602metamethod or index table (if any) for the corresponding ctype (except
603is raised if the metamethod lookup or index table lookup fails. 603for <tt>__new</tt>). An error is raised if the metamethod lookup or
604index table lookup fails.
604</p> 605</p>
605 606
606<h3 id="cdata_array">Indexing a cdata object</h3> 607<h3 id="cdata_array">Indexing a cdata object</h3>
@@ -669,7 +670,12 @@ to <tt>foo.c</tt>.
669<ul> 670<ul>
670 671
671<li><b>Constructor</b>: a ctype object can be called and used as a 672<li><b>Constructor</b>: a ctype object can be called and used as a
672<a href="ext_ffi_api.html#ffi_new">constructor</a>.</li> 673<a href="ext_ffi_api.html#ffi_new">constructor</a>. This is equivalent
674to <tt>ffi.new(ct, ...)</tt>, unless a <tt>__new</tt> metamethod is
675defined. The <tt>__new</tt> metamethod is called with the ctype object
676plus any other arguments passed to the contructor. Note that you have to
677use <tt>ffi.new</tt> inside of it, since calling <tt>ct(...)</tt> would
678cause infinite recursion.</li>
673 679
674<li><b>C&nbsp;function call</b>: a cdata function or cdata function 680<li><b>C&nbsp;function call</b>: a cdata function or cdata function
675pointer can be called. The passed arguments are 681pointer can be called. The passed arguments are
diff --git a/src/lib_ffi.c b/src/lib_ffi.c
index f4097041..e7d31fe7 100644
--- a/src/lib_ffi.c
+++ b/src/lib_ffi.c
@@ -206,31 +206,34 @@ LJLIB_CF(ffi_meta___concat) LJLIB_REC(cdata_arith MM_concat)
206 return ffi_arith(L); 206 return ffi_arith(L);
207} 207}
208 208
209/* Handle ctype __call metamethod. */
210static int ffi_call_meta(lua_State *L, CTypeID id)
211{
212 CTState *cts = ctype_cts(L);
213 CType *ct = ctype_raw(cts, id);
214 cTValue *tv;
215 if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
216 tv = lj_ctype_meta(cts, id, MM_call);
217 if (!tv)
218 lj_err_callerv(L, LJ_ERR_FFI_BADCALL, strdata(lj_ctype_repr(L, id, NULL)));
219 return lj_meta_tailcall(L, tv);
220}
221
222/* Forward declaration. */ 209/* Forward declaration. */
223static int lj_cf_ffi_new(lua_State *L); 210static int lj_cf_ffi_new(lua_State *L);
224 211
225LJLIB_CF(ffi_meta___call) LJLIB_REC(cdata_call) 212LJLIB_CF(ffi_meta___call) LJLIB_REC(cdata_call)
226{ 213{
214 CTState *cts = ctype_cts(L);
227 GCcdata *cd = ffi_checkcdata(L, 1); 215 GCcdata *cd = ffi_checkcdata(L, 1);
228 int ret; 216 CTypeID id = cd->typeid;
229 if (cd->typeid == CTID_CTYPEID) 217 CType *ct;
230 return lj_cf_ffi_new(L); 218 cTValue *tv;
231 if ((ret = lj_ccall_func(L, cd)) < 0) 219 MMS mm = MM_call;
232 return ffi_call_meta(L, cd->typeid); 220 if (cd->typeid == CTID_CTYPEID) {
233 return ret; 221 id = *(CTypeID *)cdataptr(cd);
222 mm = MM_new;
223 } else {
224 int ret = lj_ccall_func(L, cd);
225 if (ret >= 0)
226 return ret;
227 }
228 /* Handle ctype __call/__new metamethod. */
229 ct = ctype_raw(cts, id);
230 if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
231 tv = lj_ctype_meta(cts, id, mm);
232 if (tv)
233 return lj_meta_tailcall(L, tv);
234 else if (mm == MM_call)
235 lj_err_callerv(L, LJ_ERR_FFI_BADCALL, strdata(lj_ctype_repr(L, id, NULL)));
236 return lj_cf_ffi_new(L);
234} 237}
235 238
236LJLIB_CF(ffi_meta___add) LJLIB_REC(cdata_arith MM_add) 239LJLIB_CF(ffi_meta___add) LJLIB_REC(cdata_arith MM_add)
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index 3097cbf0..95d09e48 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -941,30 +941,36 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd)
941 return 0; 941 return 0;
942} 942}
943 943
944/* Record ctype call metamethod. */ 944void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd)
945static void crec_call_meta(jit_State *J, RecordFFData *rd, CTypeID id)
946{ 945{
947 CTState *cts = ctype_ctsG(J2G(J)); 946 CTState *cts = ctype_ctsG(J2G(J));
948 CType *ct = ctype_raw(cts, id); 947 GCcdata *cd = argv2cdata(J, J->base[0], &rd->argv[0]);
948 CTypeID id = cd->typeid;
949 CType *ct;
949 cTValue *tv; 950 cTValue *tv;
951 MMS mm = MM_call;
952 if (id == CTID_CTYPEID) {
953 id = crec_constructor(J, cd, J->base[0]);
954 mm = MM_new;
955 } else if (crec_call(J, rd, cd)) {
956 return;
957 }
958 /* Record ctype __call/__new metamethod. */
959 ct = ctype_raw(cts, id);
950 if (ctype_isptr(ct->info)) id = ctype_cid(ct->info); 960 if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
951 tv = lj_ctype_meta(cts, id, MM_call); 961 tv = lj_ctype_meta(cts, id, mm);
952 if (tv && tvisfunc(tv)) { 962 if (tv) {
953 J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME; 963 if (tvisfunc(tv)) {
954 rd->nres = -1; /* Pending tailcall. */ 964 J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME;
955 } else { 965 rd->nres = -1; /* Pending tailcall. */
956 /* NYI: non-function metamethods. */ 966 return;
957 lj_trace_err(J, LJ_TRERR_BADTYPE); 967 }
968 } else if (mm == MM_new) {
969 crec_alloc(J, rd, id);
970 return;
958 } 971 }
959} 972 /* No metamethod or NYI: non-function metamethods. */
960 973 lj_trace_err(J, LJ_TRERR_BADTYPE);
961void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd)
962{
963 GCcdata *cd = argv2cdata(J, J->base[0], &rd->argv[0]);
964 if (cd->typeid == CTID_CTYPEID)
965 crec_alloc(J, rd, crec_constructor(J, cd, J->base[0]));
966 else if (!crec_call(J, rd, cd))
967 crec_call_meta(J, rd, cd->typeid);
968} 974}
969 975
970static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm) 976static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm)
diff --git a/src/lj_obj.h b/src/lj_obj.h
index 43ed9204..d7e8ec09 100644
--- a/src/lj_obj.h
+++ b/src/lj_obj.h
@@ -437,6 +437,12 @@ enum {
437#define setvmstate(g, st) ((g)->vmstate = ~LJ_VMST_##st) 437#define setvmstate(g, st) ((g)->vmstate = ~LJ_VMST_##st)
438 438
439/* Metamethods. ORDER MM */ 439/* Metamethods. ORDER MM */
440#ifdef LJ_HASFFI
441#define MMDEF_FFI(_) _(new)
442#else
443#define MMDEF_FFI(_)
444#endif
445
440#ifdef LUAJIT_ENABLE_LUA52COMPAT 446#ifdef LUAJIT_ENABLE_LUA52COMPAT
441#define MMDEF_52(_) _(pairs) _(ipairs) 447#define MMDEF_52(_) _(pairs) _(ipairs)
442#else 448#else
@@ -450,7 +456,7 @@ enum {
450 /* The following must be in ORDER ARITH. */ \ 456 /* The following must be in ORDER ARITH. */ \
451 _(add) _(sub) _(mul) _(div) _(mod) _(pow) _(unm) \ 457 _(add) _(sub) _(mul) _(div) _(mod) _(pow) _(unm) \
452 /* The following are used in the standard libraries. */ \ 458 /* The following are used in the standard libraries. */ \
453 _(metatable) _(tostring) MMDEF_52(_) 459 _(metatable) _(tostring) MMDEF_FFI(_) MMDEF_52(_)
454 460
455typedef enum { 461typedef enum {
456#define MMENUM(name) MM_##name, 462#define MMENUM(name) MM_##name,