[Tarantool-patches] [PATCH luajit 1/4] x86/x64: Don't fuse loads across table.clear.
Sergey Bronnikov
sergeyb at tarantool.org
Tue Jan 14 17:10:02 MSK 2025
Hi, Sergey!
thanks for the patch! LGTM
On 10.01.2025 16:07, Sergey Kaplun wrote:
> From: Mike Pall <mike>
>
> Reported by Peter Cawley.
>
> (cherry picked from commit 45c88b7963de2969a9a656c03ba06ad995d7fd5f)
>
> Load fusing optimization takes into account only the presence of the
> corresponding stores, but not any calls that may affect the table
> content. This may lead to the incorrect stores if the fusing
> optimization occurs across the `table.clear()` call, leading to
> inconsistent behaviour between the JIT and the VM.
>
> This patch adds the corresponding check.
>
> Sergey Kaplun:
> * added the description and the test for the problem
>
> Part of tarantool/tarantool#10709
> ---
> src/lj_asm_x86.h | 1 +
> .../lj-1117-fuse-across-table-clear.test.lua | 36 +++++++++++++++++++
> 2 files changed, 37 insertions(+)
> create mode 100644 test/tarantool-tests/lj-1117-fuse-across-table-clear.test.lua
>
> diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h
> index 86ce3937..f47c460a 100644
> --- a/src/lj_asm_x86.h
> +++ b/src/lj_asm_x86.h
> @@ -465,6 +465,7 @@ static Reg asm_fuseload(ASMState *as, IRRef ref, RegSet allow)
> }
> } else if (ir->o == IR_ALOAD || ir->o == IR_HLOAD || ir->o == IR_ULOAD) {
> if (noconflict(as, ref, ir->o + IRDELTA_L2S, 0) &&
> + noconflict(as, ref, IR_CALLS, 0) && /* Don't cross table.clear. */
> !(LJ_GC64 && irt_isaddr(ir->t))) {
> asm_fuseahuref(as, ir->op1, xallow);
> return RID_MRM;
> diff --git a/test/tarantool-tests/lj-1117-fuse-across-table-clear.test.lua b/test/tarantool-tests/lj-1117-fuse-across-table-clear.test.lua
> new file mode 100644
> index 00000000..2f7c91d1
> --- /dev/null
> +++ b/test/tarantool-tests/lj-1117-fuse-across-table-clear.test.lua
> @@ -0,0 +1,36 @@
> +local tap = require('tap')
> +-- Test file to demonstrate LuaJIT's incorrect fusion across
> +-- `table.clear()`.
> +-- See also:https://github.com/LuaJIT/LuaJIT/issues/1117.
> +local test = tap.test('lj-1117-fuse-across-table-clear'):skipcond({
> + ['Test requires JIT enabled'] = not jit.status(),
> +})
> +
> +local ffi = require('ffi')
> +local table_clear = require('table.clear')
> +
> +test:plan(1)
> +
> +local tab = {0}
> +local alias_tab = tab
> +local result_tab = {}
> +
> +jit.opt.start('hotloop=1')
> +
> +for i = 1, 4 do
> + -- Load to be fused.
> + local value = tab[1]
> + -- Clear the alias table to trick the code flow analysis.
> + table_clear(alias_tab)
> + -- Need this cast to trigger load fusion. See `asm_comp()` for
> + -- the details. Before the patch, this fusion takes the
> + -- incorrect address of the already cleared table, which leads
> + -- to the failure of the check below.
> + result_tab[i] = ffi.cast('int64_t', value)
> + -- Revive the value.
> + tab[1] = 0
> +end
> +
> +test:samevalues(result_tab, 'no fusion across table.clear')
> +
> +test:done(true)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.tarantool.org/pipermail/tarantool-patches/attachments/20250114/12139ab3/attachment.htm>
More information about the Tarantool-patches
mailing list