From: Sergey Kaplun via Tarantool-patches <tarantool-patches@dev.tarantool.org> To: sergos <sergos@tarantool.org> Cc: tarantool-patches@dev.tarantool.org Subject: Re: [Tarantool-patches] [PATCH luajit] Add missing LJ_MAX_JSLOTS check. Date: Mon, 28 Mar 2022 13:02:38 +0300 [thread overview] Message-ID: <YkGHvqZDwNummKEL@root> (raw) In-Reply-To: <A3F8323A-8A97-4DFF-AB90-A6521383AE77@tarantool.org> Hi, Sergos! Thanks for the review! On 25.03.22, sergos wrote: > Hi! > > Thanks for the patch! > Some nits in comments and I have exactly the same test result > with and without the patch: > > root@dev1:/workspaces/t.sergos/third_party/luajit/test/tarantool-tests# ../../src/luajit fix-slot-check-for-mm-record.test.lua > TAP version 13 > 1..2 > ok - nil > ok - nil > > for the reference - GC64 is off: > root@dev1:/workspaces/t.sergos/third_party/luajit/test/tarantool-tests# ../../src/luajit -e "print(require('ffi').abi('gc64'))" > false Have you enabled assertions in debug build? | $ ../../src/luajit fix-slot-check-for-mm-record.test.lua | TAP version 13 | 1..2 | luajit: /home/burii/builds_workspace/luajit/fix-slot-check-for-mm-record/src/lj_record.c:92: rec_check_slots: Assertion `nslots < 250' failed. | Aborted I've done this as the following: | $ cmake . -DCMAKE_BUILD_TYPE=Debug -DLUA_USE_APICHECK=ON -DLUA_USE_ASSERT=ON -DLUAJIT_ENABLE_GC64=OFF && make -j > > Regards, > Sergos > > > On 22 Oct 2021, at 14:46, Sergey Kaplun <skaplun@tarantool.org> wrote: > > > > From: Mike Pall <mike> I reformulated commit message as you suggested: =================================================================== Add missing LJ_MAX_JSLOTS check. Thanks to Yichun Zhang. (cherry picked from commit 630ff3196a06353c6a7ccd1e9ac3958f4a8ca13c) JIT compiler doesn't check slots overflow for recording of metamethods call. Slots limit (`LJ_MAX_JSLOTS` is 250) overflow assertion fails in `rec_check_slots()` when we record metamethod call (`J->baseslot` diff + `J->maxslot` ~ 5-8 stack slots), while almost all slots of JIT engine are occupied. This patch adds the corresponding check in `lj_record_call()`. Sergey Kaplun: * added the description and the test for the problem Part of tarantool/tarantool#6548 =================================================================== Branch is force pushed. > > > > Thanks to Yichun Zhang. > > > > (cherry picked from commit 630ff3196a06353c6a7ccd1e9ac3958f4a8ca13c) > > > > Before the patch, JIT compiler doesn't check slots overflow for > > Shall we put it like “before the patch”? We’re describing current behavior, > which is apparently without the patch. Then we can use simple present tense. Fixed. > > > recording of metamethods call. So the assertion in `rec_check_slots()` > > checking that we don't overflow the slots limit (the limit > > `LJ_MAX_JSLOTS` is 250) is failing, > > Slots limit overflow assertion fails in `rec_check_slots()` Fixed. > > > when we record metamethod call > > (`J->baseslot` diff + `J->maxslot` ~ 5-8 stack slots), while almost all > > slots of JIT engine are occupied. > > > > unlike the `lj_record_call()` (if I got it right?) during a metamethod > recording. We pass to `lj_record_call()` from any metamethod and this condition isn't checked. > > > This patch adds the corresponding check in `lj_record_call()`. > > > > Sergey Kaplun: > > * added the description and the test for the problem > > --- > > > > Tarantool branch: https://github.com/tarantool/tarantool/tree/skaplun/gh-noticket-fix-slot-check-for-mm-record > > Branch: https://github.com/tarantool/luajit/tree/skaplun/gh-noticket-fix-slot-check-for-mm-record > > > > src/lj_record.c | 2 + > > .../fix-slot-check-for-mm-record.test.lua | 81 +++++++++++++++++++ > > 2 files changed, 83 insertions(+) > > create mode 100644 test/tarantool-tests/fix-slot-check-for-mm-record.test.lua > > > > diff --git a/src/lj_record.c b/src/lj_record.c > > index 42af09e5..adf2370e 100644 > > --- a/src/lj_record.c > > +++ b/src/lj_record.c > > @@ -731,6 +731,8 @@ void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs) > > J->framedepth++; > > J->base += func+1+LJ_FR2; > > J->baseslot += func+1+LJ_FR2; > > + if (J->baseslot + J->maxslot >= LJ_MAX_JSLOTS) > > + lj_trace_err(J, LJ_TRERR_STACKOV); > > } > > > > /* Record tail call. */ > > diff --git a/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua b/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua > > new file mode 100644 > > index 00000000..e361830d > > --- /dev/null > > +++ b/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua > > @@ -0,0 +1,81 @@ > > +local tap = require('tap') > > + > > +local test = tap.test('fix-slot-check-for-mm-record') > > +test:plan(2) > > + > > +-- Before the patch, JIT compiler doesn't check slots overflow > > +-- for recording of metamethods call. So the assertion checking > > +-- that we don't overflow the slots limit (the limit > > +-- `LJ_MAX_JSLOTS` is 250) is failing, when we record metamethod > > +-- call (`J->baseslot` diff + `J->maxslot` ~ 5-8 stack slots), > > +-- while almost all slots of JIT engine are occupied. > > + > > +-- Table with the simplest metamethod to call. > > +local a0 = setmetatable({}, { > > + __add = function(t, arg1) > > + t[arg1] = arg1 > > + end > > +}) > > +_G.a0 = a0 > > + > > +-- Fixarg function with call to metamethod. > > +local function a1() > > + -- This constant is not setted as an upvalue to simplify stack > ^^^^^^ set > > + -- slots counting. Just remember that it is 42. > > + return a0 + 42 > > +end > > +_G.a1 = a1 > > + > > +-- Generate bunch of functions to call them recursively. > > +-- Each function is a vararg function bumps slots on > > +-- 2 (4) = 1 (2) * 2 for usual Lua frame and vararg frame > > +-- recording for GC32 (GC64). > > +for i = 2, 121 do > > + local f, err = load(('local r = a%d() return r'):format(i - 1)) > > + assert(f, err) > > + _G['a'..i] = f > > +end > > + > > +-- Trace is long enough, so we need to increase maxrecord. > > +jit.opt.start('hotloop=1', 'maxrecord=2048') > > + > > +local function test_gc32() > > + -- 1 - Base slot. > > + -- 3 slots for cycle start, stop, step. > > + for _ = 1, 4 do > > + -- Occupy 1 slot for the function itself + 2 next slots will > > + -- occupied for a call to the vararg function. > > + -- Need 121 calls: 7 (baseslot after `a121()` is recorded) > > + -- + 119 * 2 + 1 (`a1` -- is not vararg function) = 246 slots. > > + -- The next call of metamethod in `a0` to record have 2 args > > + -- + 2 slots for metamethod function + 1 slot for frame. > > + -- luacheck: no global > > + a121() > > + assert(a0[42] == 42) > > + a0[42] = nil > > + end > > + return true > > +end > > + > > +local function test_gc64() > > + -- 2 - Base slot. > > + -- 3 slots for cycle start, stop, step. > > + for _ = 1, 4 do > > + -- Occupy 1 slot for the function itself + 4 next slots will > > + -- occupied for a call to the vararg function. > > + -- Need 60 calls: 10 (baseslot after `a60()` is recorded) > > + -- + 58 * 4 + 2 (`a1` -- is not vararg function) = 244 slots. > > + -- The next call of metamethod in `a0` to record have 2 args > > + -- + 3 slots for metamethod function + 2 slots for frame. > > + -- luacheck: no global > > + a60() > > + assert(a0[42] == 42) > > + a0[42] = nil > > + end > > + return true > > +end > > + > > +test:ok(test_gc32()) > > +test:ok(test_gc64()) > > + > > +os.exit(test:check() and 0 or 1) > > -- > > 2.31.0 > > > -- Best regards, Sergey Kaplun
next prev parent reply other threads:[~2022-03-28 10:04 UTC|newest] Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-10-22 11:46 Sergey Kaplun via Tarantool-patches 2022-03-25 15:51 ` sergos via Tarantool-patches 2022-03-28 10:02 ` Sergey Kaplun via Tarantool-patches [this message] 2022-03-30 10:02 ` sergos via Tarantool-patches 2022-04-06 7:21 ` Sergey Kaplun via Tarantool-patches 2022-06-27 19:58 ` Igor Munkin via Tarantool-patches 2022-06-28 6:39 ` Sergey Kaplun via Tarantool-patches 2022-06-30 12:08 ` Igor Munkin via Tarantool-patches
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=YkGHvqZDwNummKEL@root \ --to=tarantool-patches@dev.tarantool.org \ --cc=sergos@tarantool.org \ --cc=skaplun@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH luajit] Add missing LJ_MAX_JSLOTS check.' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox