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 3/3] ARM64: Prevent STP fusion for conditional code emitted by TBAR.
Date: Mon, 25 Aug 2025 18:12:25 +0300 [thread overview]
Message-ID: <89fc7745-5d9b-48d1-9834-df58964df888@tarantool.org> (raw)
In-Reply-To: <6a0d3fabe8caca468e02a319a45db6f2556dd2fe.1753344905.git.skaplun@tarantool.org>
[-- Attachment #1: Type: text/plain, Size: 5825 bytes --]
Hi, Sergey!
thanks for the patch and a good explanation in the commit message!
LGTM
Sergey
On 7/24/25 12:04, Sergey Kaplun wrote:
> From: Mike Pall <mike>
>
> Thanks to Peter Cawley.
>
> (cherry picked from commit 7cc53f0b85f834dfba1516ea79d59db463e856fa)
>
> Assume we have a trace for the several `setmetatable()` calls to the
> same table. This trace contains the following IR:
> | 0011 p64 FREF 0003 tab.meta
> | ...
> | 0018 x0 > tab TNEW 0 0
> | 0019 tab TBAR 0003
> | 0020 tab FSTORE 0011 0018
>
> The expected mcode to be emitted for the last two IRs is the following:
> | 55626cffb0 ldrb w30, [x19, 8] ; tab->marked
> | 55626cffb4 tst w30, 0x4 ; Is black?
> | 55626cffb8 beq 0x626cffd0 ; Skip marking.
> | 55626cffbc ldr x27, [x20, 128]
> | 55626cffc0 and w30, w30, 0xfffffffb
> | 55626cffc4 str x19, [x20, 128]
> | 55626cffcc strb w30, [x19, 8] ; tab->marked
> | 55626cffc8 str x27, [x19, 24] ; tab->gclist
> | 55626cffd0 str x0, [x19, 32] ; tab->metatable
>
> But the last 2 instructions are fused into the following `stp`:
> | 55581dffd0 stp x27, x0, [x19, 48]
> Hence, the GC propagation frontier back is done partially, since
> `str x27, [x19, 24]` is not skipped despite TBAR semantics. This leads
> to the incorrect value in the `gclist` and the segmentation fault during
> its traversal on GC step.
>
> This patch prevents this fusion via switching instruction for
> `tab->gclist` and `tab->marked` storing.
>
> Sergey Kaplun:
> * added the description and the test for the problem
>
> Part of tarantool/tarantool#11691
> ---
> src/lj_asm_arm64.h | 3 +-
> ...1057-arm64-stp-fusing-across-tbar.test.lua | 79 +++++++++++++++++++
> 2 files changed, 81 insertions(+), 1 deletion(-)
> create mode 100644 test/tarantool-tests/lj-1057-arm64-stp-fusing-across-tbar.test.lua
>
> diff --git a/src/lj_asm_arm64.h b/src/lj_asm_arm64.h
> index 5a6c60b7..9b3c0467 100644
> --- a/src/lj_asm_arm64.h
> +++ b/src/lj_asm_arm64.h
> @@ -1271,8 +1271,9 @@ static void asm_tbar(ASMState *as, IRIns *ir)
> Reg link = ra_scratch(as, rset_exclude(RSET_GPR, tab));
> Reg mark = RID_TMP;
> MCLabel l_end = emit_label(as);
> - emit_lso(as, A64I_STRx, link, tab, (int32_t)offsetof(GCtab, gclist));
> emit_lso(as, A64I_STRB, mark, tab, (int32_t)offsetof(GCtab, marked));
> + /* Keep STRx in the middle to avoid LDP/STP fusion with surrounding code. */
> + emit_lso(as, A64I_STRx, link, tab, (int32_t)offsetof(GCtab, gclist));
> emit_setgl(as, tab, gc.grayagain);
> emit_dn(as, A64I_ANDw^emit_isk13(~LJ_GC_BLACK, 0), mark, mark);
> emit_getgl(as, link, gc.grayagain);
> diff --git a/test/tarantool-tests/lj-1057-arm64-stp-fusing-across-tbar.test.lua b/test/tarantool-tests/lj-1057-arm64-stp-fusing-across-tbar.test.lua
> new file mode 100644
> index 00000000..27d18916
> --- /dev/null
> +++ b/test/tarantool-tests/lj-1057-arm64-stp-fusing-across-tbar.test.lua
> @@ -0,0 +1,79 @@
> +local tap = require('tap')
> +
> +-- This test demonstrates LuaJIT's incorrect fusing of store
> +-- instructions separated by the conditional branch on arm64.
> +-- See alsohttps://github.com/LuaJIT/LuaJIT/issues/1057.
> +local test = tap.test('lj-1057-arm64-stp-fusing-across-tbar'):skipcond({
> + ['Test requires JIT enabled'] = not jit.status(),
> +})
> +
> +test:plan(2)
> +
> +-- XXX: Simplify the `jit.dump()` output.
> +local setmetatable = setmetatable
> +
> +-- The function below generates the following IR:
> +-- | 0011 p64 FREF 0003 tab.meta
> +-- | ...
> +-- | 0018 x0 > tab TNEW #0 #0
> +-- | 0019 tab TBAR 0003
> +-- | 0020 tab FSTORE 0011 0018
> +-- The expected mcode to be emitted for the last two IRs is the
> +-- following:
> +-- | 55626cffb0 ldrb w30, [x19, #8] ; tab->marked
> +-- | 55626cffb4 tst w30, #0x4 ; Is black?
> +-- | 55626cffb8 beq 0x626cffd0 ; Skip marking.
> +-- | 55626cffbc ldr x27, [x20, #128]
> +-- | 55626cffc0 and w30, w30, #0xfffffffb
> +-- | 55626cffc4 str x19, [x20, #128]
> +-- | 55626cffcc strb w30, [x19, #8] ; tab->marked
> +-- | 55626cffc8 str x27, [x19, #24] ; tab->gclist
> +-- | 55626cffd0 str x0, [x19, #32] ; tab->metatable
> +--
> +-- But the last 2 instructions are fused into the following `stp`:
> +-- | 55581dffd0 stp x27, x0, [x19, #48]
> +-- Hence, the GC propagation frontier back is done partially,
> +-- since `str x27, [x19, #24]` is not skipped despite TBAR
> +-- semantics. This leads to the incorrect value in the `gclist`
> +-- and the segmentation fault during its traversal on GC step.
> +local function trace(target_t)
> + -- Precreate a table for the FLOAD to avoid TNEW in between.
> + local stack_t = {}
> + -- Generate FSTORE TBAR pair. The FSTORE will be dropped due to
> + -- the FSTORE below by DSE.
> + setmetatable(target_t, {})
> + -- Generate FSTORE. TBAR will be dropped by CSE.
> + setmetatable(target_t, stack_t)
> +end
> +
> +jit.opt.start('hotloop=1')
> +
> +-- XXX: Need to trigger the GC on trace to introspect that the
> +-- GC chain is broken. Use empirical 10000 iterations.
> +local tab = {}
> +for _ = 1, 1e4 do
> + trace(tab)
> +end
> +
> +test:ok(true, 'no assertion failure in the simple loop')
> +
> +-- The similar test, but be sure that we finish the whole GC
> +-- cycle, plus using upvalue instead of stack slot for the target
> +-- table.
> +
> +local target_t = {}
> +local function trace2()
> + local stack_t = {}
> + setmetatable(target_t, {})
> + setmetatable(target_t, stack_t)
> +end
> +
> +collectgarbage('collect')
> +collectgarbage('setstepmul', 1)
> +while not collectgarbage('step') do
> + trace2()
> +end
> +
> +test:ok(true, 'no assertion failure in the whole GC cycle')
> +
> +test:done(true)
[-- Attachment #2: Type: text/html, Size: 6180 bytes --]
next prev parent reply other threads:[~2025-08-25 15:12 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-24 9:03 [Tarantool-patches] [PATCH luajit 0/3] Generation of immediates and TBAR fusion Sergey Kaplun via Tarantool-patches
2025-07-24 9:03 ` [Tarantool-patches] [PATCH luajit 1/3] ARM64: Improve generation of immediates Sergey Kaplun via Tarantool-patches
2025-08-25 15:26 ` Sergey Bronnikov via Tarantool-patches
2025-07-24 9:03 ` [Tarantool-patches] [PATCH luajit 2/3] ARM64: More improvements to the " Sergey Kaplun via Tarantool-patches
2025-08-25 14:21 ` Sergey Bronnikov via Tarantool-patches
2025-08-27 9:08 ` Sergey Kaplun via Tarantool-patches
2025-07-24 9:04 ` [Tarantool-patches] [PATCH luajit 3/3] ARM64: Prevent STP fusion for conditional code emitted by TBAR Sergey Kaplun via Tarantool-patches
2025-08-25 15:12 ` Sergey Bronnikov via Tarantool-patches [this message]
2025-08-08 14:28 ` [Tarantool-patches] [PATCH luajit 0/3] Generation of immediates and TBAR fusion Sergey Bronnikov via Tarantool-patches
2025-08-25 15:26 ` Sergey Bronnikov 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=89fc7745-5d9b-48d1-9834-df58964df888@tarantool.org \
--to=tarantool-patches@dev.tarantool.org \
--cc=sergeyb@tarantool.org \
--cc=skaplun@tarantool.org \
--subject='Re: [Tarantool-patches] [PATCH luajit 3/3] ARM64: Prevent STP fusion for conditional code emitted by TBAR.' \
/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