From: Sergey Bronnikov via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: Sergey Kaplun <skaplun@tarantool.org>
Cc: tarantool-patches@dev.tarantool.org
Subject: Re: [Tarantool-patches] [PATCH luajit] Fix detection of inconsistent renames due to sunk values.
Date: Wed, 5 Feb 2025 14:09:31 +0300 [thread overview]
Message-ID: <14723fed-6427-47f6-8aa1-c0a404799b06@tarantool.org> (raw)
In-Reply-To: <20250203161714.7693-1-skaplun@tarantool.org>
[-- Attachment #1: Type: text/plain, Size: 6787 bytes --]
Hello, Sergey,
LGTM, thanks!
Sergey
On 03.02.2025 19:17, Sergey Kaplun wrote:
> From: Mike Pall <mike>
>
> Thanks to Sergey Kaplun.
>
> (cherry picked from commit 811e448daa0f8f06e946fb607a98ace85c43b574)
>
> This commit is a follow-up to the commit
> 3a2e4847ca257f5fda903e9374762049670b7bc0 ("Detect inconsistent renames
> even in the presence of sunk values."). Due to the reversed assembling
> order of a trace, all registers are allocated from the bottom of the
> trace to the top. Furthermore, if the snapshot contains sunk values, IRs
> for them will contain the `RID_SUNK` after the first processing. If
> there is another snapshot (with a smaller number) containing this sunk
> IR, this IR will not be processed during the bloom filter marking in the
> allocation of the slot that escapes this snapshot (since it is already
> sunk). Hence, such IRs still may lead to the rename invariant violation
> like in the aforementioned commit.
>
> This patch prevents scanning from stopping when already sunk IR is faced
> during snapshot processing so bloom filters contain actual information.
> The disadvantage of this approach is that it assumes that any sunk
> table-typed IR can't refer to the same table inside it (so there should
> not be any cycling references in the sunk table).
>
> Sergey Kaplun:
> * added the description and the test for the problem
>
> Part of tarantool/tarantool#11055
> ---
>
> Branch:https://github.com/tarantool/luajit/tree/skaplun/lj-1295-bad-renames-for-sunk-values
> Related issues:
> *https://github.com/LuaJIT/LuaJIT/issues/584
> *https://github.com/LuaJIT/LuaJIT/issues/1295
> *https://github.com/tarantool/tarantool/issues/10746
> *https://github.com/tarantool/aeon/issues/282
> *https://github.com/tarantool/tarantool/issues/11055
>
> src/lj_asm.c | 4 +-
> ...-1295-bad-renames-for-sunk-values.test.lua | 111 ++++++++++++++++++
> 2 files changed, 113 insertions(+), 2 deletions(-)
> create mode 100644 test/tarantool-tests/lj-1295-bad-renames-for-sunk-values.test.lua
>
> diff --git a/src/lj_asm.c b/src/lj_asm.c
> index f7540165..9e81dbc9 100644
> --- a/src/lj_asm.c
> +++ b/src/lj_asm.c
> @@ -903,11 +903,11 @@ static int asm_sunk_store(ASMState *as, IRIns *ira, IRIns *irs)
> static void asm_snap_alloc1(ASMState *as, IRRef ref)
> {
> IRIns *ir = IR(ref);
> - if (!irref_isk(ref) && ir->r != RID_SUNK) {
> + if (!irref_isk(ref)) {
> bloomset(as->snapfilt1, ref);
> bloomset(as->snapfilt2, hashrot(ref, ref + HASH_BIAS));
> if (ra_used(ir)) return;
> - if (ir->r == RID_SINK) {
> + if (ir->r == RID_SINK || ir->r == RID_SUNK) {
> ir->r = RID_SUNK;
> #if LJ_HASFFI
> if (ir->o == IR_CNEWI) { /* Allocate CNEWI value. */
> diff --git a/test/tarantool-tests/lj-1295-bad-renames-for-sunk-values.test.lua b/test/tarantool-tests/lj-1295-bad-renames-for-sunk-values.test.lua
> new file mode 100644
> index 00000000..9291fca4
> --- /dev/null
> +++ b/test/tarantool-tests/lj-1295-bad-renames-for-sunk-values.test.lua
> @@ -0,0 +1,111 @@
> +local tap = require('tap')
> +
> +-- Test file to demonstrate LuaJIT assembler misbehaviour.
> +-- For more info, proceed to the issues:
> +-- *https://github.com/LuaJIT/LuaJIT/issues/584,
> +-- *https://github.com/LuaJIT/LuaJIT/issues/1295,
> +-- *https://github.com/tarantool/tarantool/issues/10746.
> +
> +local test = tap.test('lj-1295-bad-renames-for-sunk-values'):skipcond({
> + ['Test requires JIT enabled'] = not jit.status(),
> +})
> +
> +test:plan(1)
> +
> +-- XXX: The reproducer requires specific snapshotting and register
> +-- allocations, so the reproducer mostly copies the relevant code
> +-- fromhttps://github.com/luafun/luafun.
> +
> +----- Related part of luafun.lua. --------------------------------
> +
> +local iterator_mt = {
> + -- Usually called by the for-in loop.
> + __call = function(self, param, state)
> + return self.gen(param, state)
> + end,
> +}
> +
> +local wrap = function(gen, param, state)
> + return setmetatable({
> + gen = gen,
> + param = param,
> + state = state
> + }, iterator_mt), param, state
> +end
> +
> +-- These functions call each other to implement a flat iterator
> +-- over the several iterable objects.
> +local chain_gen_r1
> +local chain_gen_r2 = function(param, state, state_x, ...)
> + if state_x == nil then
> + local i = state[1]
> + i = i + 1
> + if param[3 * i - 2] == nil then
> + return nil
> + end
> + return chain_gen_r1(param, {i, param[3 * i]})
> + end
> + return {state[1], state_x}, ...
> +end
> +
> +chain_gen_r1 = function(param, state)
> + local i, _ = state[1], state[2]
> + local gen_x, param_x = param[3 * i - 2], param[3 * i - 1]
> + return chain_gen_r2(param, state, gen_x(param_x, state[2]))
> +end
> +
> +local chain = function(...)
> + local n = select('#', ...)
> + local param = { [3 * n] = 0 }
> + local gen_x, param_x, state_x
> + for i = 1, n do
> + local elem = select(i, ...)
> + -- Put gen, param, state into param table.
> + gen_x, param_x, state_x = wrap(ipairs(elem))
> + param[3 * i - 2] = gen_x
> + param[3 * i - 1] = param_x
> + param[3 * i] = state_x
> + end
> +
> + return wrap(chain_gen_r1, param, {1, param[3]})
> +end
> +
> +----- Reproducer. ------------------------------------------------
> +
> +-- XXX: Should be different tables.
> +local a = {{'a'}, {'a'}}
> +local b = {{'a'}, {'a'}}
> +
> +-- XXX: Here one can find the rationale for the 'hotloop' value.
> +-- 1. The innermost loop in a bunch of calls tries to compile the
> +-- `__call` metamethod first, but this trace is aborted due to
> +-- leaving the `for _ in` loop.
> +-- 2. The trace we are interested in started to compile: this is
> +-- the inner `for _ in` loop with the full inlined body.
> +--
> +-- The chain loop in this case iterates over 4 elements. Hence, 2
> +-- iterations of the outer loop are not enough. The trace
> +-- mentioned in 2 is recorded on the 8th inner cycle iteration but
> +-- never started. Hence, let's run 3 iterations of the outer loop
> +-- instead.
> +
> +-- JIT fine-tuning via the 'hotloop' option allows us to catch
> +-- this elusive case, which we achieved in the last bullet. The
> +-- reason why this case leads to misbehaviour while restoring the
> +-- guest stack at the trace exit is described in the following
> +-- LuaJIT issue:https://github.com/LuaJIT/LuaJIT/issues/1295.
> +
> +-- Specific `hotloop` to get only one trace we are interested in.
> +jit.opt.start('hotloop=7')
> +
> +xpcall(function()
> + for _ = 1, 3 do
> + for _ in chain(a, b) do
> + end
> + end
> + test:ok('All emitted RENAMEs are fine')
> +end, function()
> + test:fail('Invalid Lua stack has been restored')
> +end)
> +
> +test:done(true)
[-- Attachment #2: Type: text/html, Size: 8019 bytes --]
prev parent reply other threads:[~2025-02-05 11:09 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-03 16:17 Sergey Kaplun via Tarantool-patches
2025-02-05 11:09 ` Sergey Bronnikov via Tarantool-patches [this message]
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=14723fed-6427-47f6-8aa1-c0a404799b06@tarantool.org \
--to=tarantool-patches@dev.tarantool.org \
--cc=sergeyb@tarantool.org \
--cc=skaplun@tarantool.org \
--subject='Re: [Tarantool-patches] [PATCH luajit] Fix detection of inconsistent renames due to sunk values.' \
/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