aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2012-06-20 18:24:49 +0200
committerMike Pall <mike>2012-06-20 18:28:25 +0200
commit8b71ab108053c12bc2de9c1de0f786387a2b75e5 (patch)
tree98be8d9138d3cb13dac67f5f7621b0bf09bb0fc7 /src
parente9e45313e737579bc6db4f74942bcd66e95532c1 (diff)
downloadluajit-8b71ab108053c12bc2de9c1de0f786387a2b75e5.tar.gz
luajit-8b71ab108053c12bc2de9c1de0f786387a2b75e5.tar.bz2
luajit-8b71ab108053c12bc2de9c1de0f786387a2b75e5.zip
FFI: Check for __new metamethod when calling a constructor.
Diffstat (limited to 'src')
-rw-r--r--src/lib_ffi.c41
-rw-r--r--src/lj_crecord.c44
-rw-r--r--src/lj_obj.h8
3 files changed, 54 insertions, 39 deletions
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,