From ae79ff4e53392f80c4e64a043800c6838ab535a0 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Mon, 14 Nov 2011 12:01:48 +0100 Subject: [PATCH] FFI: Resolve __call metamethod for pointers, too. --- src/lib_ffi.c | 5 ++++- src/lj_crecord.c | 19 ++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/lib_ffi.c b/src/lib_ffi.c index 82942e44..af500118 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c @@ -207,7 +207,10 @@ LJLIB_CF(ffi_meta___concat) LJLIB_REC(cdata_arith MM_concat) static int ffi_call_meta(lua_State *L, CTypeID id) { CTState *cts = ctype_cts(L); - cTValue *tv = lj_ctype_meta(cts, id, MM_call); + CType *ct = ctype_raw(cts, id); + cTValue *tv; + if (ctype_isptr(ct->info)) id = ctype_cid(ct->info); + tv = lj_ctype_meta(cts, id, MM_call); if (!tv) lj_err_callerv(L, LJ_ERR_FFI_BADCALL, strdata(lj_ctype_repr(L, id, NULL))); return lj_meta_tailcall(L, tv); diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 3dd6f495..2c63e8a6 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -890,13 +890,30 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) return 0; } +/* Record ctype call metamethod. */ +static void crec_call_meta(jit_State *J, RecordFFData *rd, CTypeID id) +{ + CTState *cts = ctype_ctsG(J2G(J)); + CType *ct = ctype_raw(cts, id); + cTValue *tv; + if (ctype_isptr(ct->info)) id = ctype_cid(ct->info); + tv = lj_ctype_meta(cts, id, MM_call); + if (tv && tvisfunc(tv)) { + J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME; + rd->nres = -1; /* Pending tailcall. */ + } else { + /* NYI: non-function metamethods. */ + lj_trace_err(J, LJ_TRERR_BADTYPE); + } +} + void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd) { GCcdata *cd = argv2cdata(J, J->base[0], &rd->argv[0]); if (cd->typeid == CTID_CTYPEID) crec_alloc(J, rd, crec_constructor(J, cd, J->base[0])); else if (!crec_call(J, rd, cd)) - lj_trace_err(J, LJ_TRERR_BADTYPE); + crec_call_meta(J, rd, cd->typeid); } static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm)