diff options
author | Mike Pall <mike> | 2012-06-20 18:24:49 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2012-06-20 18:28:25 +0200 |
commit | 8b71ab108053c12bc2de9c1de0f786387a2b75e5 (patch) | |
tree | 98be8d9138d3cb13dac67f5f7621b0bf09bb0fc7 /src | |
parent | e9e45313e737579bc6db4f74942bcd66e95532c1 (diff) | |
download | luajit-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.c | 41 | ||||
-rw-r--r-- | src/lj_crecord.c | 44 | ||||
-rw-r--r-- | src/lj_obj.h | 8 |
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. */ | ||
210 | static 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. */ |
223 | static int lj_cf_ffi_new(lua_State *L); | 210 | static int lj_cf_ffi_new(lua_State *L); |
224 | 211 | ||
225 | LJLIB_CF(ffi_meta___call) LJLIB_REC(cdata_call) | 212 | LJLIB_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 | ||
236 | LJLIB_CF(ffi_meta___add) LJLIB_REC(cdata_arith MM_add) | 239 | LJLIB_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. */ | 944 | void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd) |
945 | static 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); | |
961 | void 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 | ||
970 | static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm) | 976 | static 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 | ||
455 | typedef enum { | 461 | typedef enum { |
456 | #define MMENUM(name) MM_##name, | 462 | #define MMENUM(name) MM_##name, |