Hi, Sergey, thanks for the patch! LGTM Sergey On 3/16/26 13:48, Sergey Kaplun wrote: > From: Mike Pall > > Reported by Vladimir Davydov and Sergey Kaplun. > > (cherry picked from commit 02e29995581cb568a784a9b996cd5e9139cd0737) > > This patch is a follow-up for the commit > 6cee1333ef2b340e1b23e3051b9f433fc803d2ff ("FFI: Resolve metamethods for > constructors, too."). It allows the use of metamethods of the objects to > be called on their constructors. Unfortunately, the JIT part isn't > updated and may cause inconsistencies since it is indexing the field of > the structure referenced by the given CType. > > This patch makes the semantics of JIT the same as for the VM. > > Sergey Kaplun: > * added the description and the test for the problem > > Part of tarantool/tarantool#12134 > --- > > Branch:https://github.com/tarantool/luajit/tree/skaplun/lj-1441-record-constructor-metamethod > Related issues: > *https://github.com/LuaJIT/LuaJIT/issues/1441 > *https://github.com/tarantool/tarantool/issues/12134 > > src/lj_crecord.c | 2 + > ...441-record-constructor-metamethod.test.lua | 79 +++++++++++++++++++ > 2 files changed, 81 insertions(+) > create mode 100644 test/tarantool-tests/lj-1441-record-constructor-metamethod.test.lua > > diff --git a/src/lj_crecord.c b/src/lj_crecord.c > index b016eaec..d486ee85 100644 > --- a/src/lj_crecord.c > +++ b/src/lj_crecord.c > @@ -881,6 +881,8 @@ again: > } > J->base[0] = lj_ir_kint(J, (int32_t)fct->size); > return; /* Interpreter will throw for newindex. */ > + } else if (cd && cd->ctypeid == CTID_CTYPEID) { > + /* Only resolve constants and metamethods for constructors. */ > } else if (ctype_isbitfield(fct->info)) { > if (ofs) > ptr = emitir(IRT(IR_ADD, IRT_PTR), ptr, lj_ir_kintp(J, ofs)); > diff --git a/test/tarantool-tests/lj-1441-record-constructor-metamethod.test.lua b/test/tarantool-tests/lj-1441-record-constructor-metamethod.test.lua > new file mode 100644 > index 00000000..370e49e0 > --- /dev/null > +++ b/test/tarantool-tests/lj-1441-record-constructor-metamethod.test.lua > @@ -0,0 +1,79 @@ > +local tap = require('tap') > + > +-- The test file to demonstrate LuaJIT's incorrect recording of > +-- the __index metamethod invocation on the cdata's constructor. > +-- See also:https://github.com/LuaJIT/LuaJIT/issues/1441. > + > +local test = tap.test('lj-1441-record-constructor-metamethod'):skipcond({ > + ['Test requires JIT enabled'] = not jit.status(), > +}) > + > +test:plan(3) > + > +local ffi = require('ffi') > + > +ffi.cdef[[ > + struct test_recursive {int a;}; > + struct test_finite {int a;}; > +]] > + > +local recursive_t = ffi.typeof('struct test_recursive') > +local finite_t = ffi.typeof('struct test_finite') > + > +local MAGIC = 42 > + > +local function new_recursive() > + return ffi.new(recursive_t, 0) > +end > + > +local function new_finite() > + return ffi.new(finite_t, 0) > +end > + > +local function index_func_recursive(v) > + -- Should raise an error (stack overflow). > + return ffi.typeof(v).a > +end > + > +-- Special object to invoke metamethod on the cdata. > +local one_more_step = new_finite() > + > +local function index_func_finite(v) > + if v == one_more_step then > + -- XXX: Avoid tail-calls. > + local x = ffi.typeof(v).a > + return x > + else > + return MAGIC > + end > +end > + > +ffi.metatype(recursive_t, { > + __index = index_func_recursive, > +}) > + > +ffi.metatype(finite_t, { > + __index = index_func_finite, > +}) > + > +jit.opt.start('hotloop=1') > + > +-- Test the recursive call. Expect the stack overflow error. > +local o_rec = new_recursive() > +local result, errmsg > +for _ = 1, 4 do > + result, errmsg = pcall(index_func_recursive, o_rec) > +end > + > +test:ok(not result, 'correct status for recursive call') > +test:like(errmsg, 'stack overflow', 'correct error message for recursive call') > + > +-- Test the finite call. Expect the specific value. > +local got > +for _ = 1, 4 do > + got = index_func_finite(one_more_step) > +end > + > +test:is(got, MAGIC, 'correct result value on trace for finite call') > + > +test:done(true)