[Tarantool-patches] [PATCH luajit v2] Mark CONV as non-weak, to prevent elimination of its side-effect.

Maksim Kokryashkin max.kokryashkin at gmail.com
Tue Oct 3 16:37:03 MSK 2023


From: Mike Pall <mike>

An unused guarded CONV int.num cannot be omitted in general.

(cherry-picked from commit 881d02d3117838acaf4fb844332c8e33cc95c8c5)

In some cases, an unused `CONV int.num` omission in `DUALNUM` mode
may lead to a guard absence, resulting in invalid control flow
branching and undefined behavior. For a comprehensive example of
the described situation, please refer to the comment
in `test/tarantool-tests/mark-conv-non-weak.test.lua`.

Maxim Kokryashkin:
* added the description and the test for the problem

Part of tarantool/tarantool#9145
---
Branch: https://github.com/tarantool/luajit/tree/fckxorg/mark-conv-non-weak
PR: https://github.com/tarantool/tarantool/pull/8871

Changes in v2:
- Fixed comments as per review by Sergey Kaplun
 src/lj_ir.h                                   |   2 +-
 .../mark-conv-non-weak.test.lua               | 115 ++++++++++++++++++
 2 files changed, 116 insertions(+), 1 deletion(-)
 create mode 100644 test/tarantool-tests/mark-conv-non-weak.test.lua

diff --git a/src/lj_ir.h b/src/lj_ir.h
index 46af54e4..e3ba6ff3 100644
--- a/src/lj_ir.h
+++ b/src/lj_ir.h
@@ -132,7 +132,7 @@
   _(XBAR,	S , ___, ___) \
   \
   /* Type conversions. */ \
-  _(CONV,	NW, ref, lit) \
+  _(CONV,	N , ref, lit) \
   _(TOBIT,	N , ref, ref) \
   _(TOSTR,	N , ref, lit) \
   _(STRTO,	N , ref, ___) \
diff --git a/test/tarantool-tests/mark-conv-non-weak.test.lua b/test/tarantool-tests/mark-conv-non-weak.test.lua
new file mode 100644
index 00000000..f54f30ba
--- /dev/null
+++ b/test/tarantool-tests/mark-conv-non-weak.test.lua
@@ -0,0 +1,115 @@
+local tap = require('tap')
+local test = tap.test('mark-conv-non-weak'):skipcond({
+    ['Test requires JIT enabled'] = not jit.status(),
+})
+
+test:plan(1)
+
+local data = {0.1, 0, 0.1, 0, 0 / 0}
+local sum = 0
+
+jit.opt.start('hotloop=2', 'hotexit=2')
+
+-- XXX: The test fails before the patch only
+-- for `DUALNUM` mode. All of the IRs below are
+-- produced by the corresponding LuaJIT build.
+
+-- When the trace is recorded, the IR
+-- is the following before the patch:
+---- TRACE 1 IR
+-- ....        SNAP   #0   [ ---- ---- ---- ---- ---- ---- ---- ---- ---- ]
+-- 0001    u8  XLOAD  [0x100dac521]  V
+-- 0002    int BAND   0001  +12
+-- 0003 >  int EQ     0002  +0
+-- 0004 >  int SLOAD  #8    T
+-- ....        SNAP   #1   [ ---- ---- ---- ---- ---- ---- ---- ---- ---- ]
+-- 0005 >  num SLOAD  #3    T
+-- 0006    num CONV   0004  num.int
+-- 0007  + num ADD    0006  0005
+-- 0008 >  fun SLOAD  #4    T
+-- 0009 >  tab SLOAD  #5    T
+-- 0010 >  int SLOAD  #6    T
+-- 0011 >  fun EQ     0008  ipairs_aux
+-- 0012  + int ADD    0010  +1
+-- 0013    int FLOAD  0009  tab.asize
+-- 0014 >  int ABC    0013  0012
+-- 0015    p64 FLOAD  0009  tab.array
+-- 0016    p64 AREF   0015  0012
+-- 0017 >+ num ALOAD  0016
+-- ....        SNAP   #2   [ ---- ---- ---- 0007 ---- ---- 0012 0012 0017 ]
+-- 0018 ------ LOOP ------------
+-- 0019    u8  XLOAD  [0x100dac521]  V
+-- 0020    int BAND   0019  +12
+-- 0021 >  int EQ     0020  +0
+-- 0022 >  int CONV   0017  int.num
+-- ....        SNAP   #3   [ ---- ---- ---- 0007 ---- ---- 0012 0012 0017 ]
+-- 0023  + num ADD    0017  0007
+-- 0024  + int ADD    0012  +1
+-- 0025 >  int ABC    0013  0024
+-- 0026    p64 AREF   0015  0024
+-- 0027 >+ num ALOAD  0026
+-- 0028    num PHI    0017  0027
+-- 0029    num PHI    0007  0023
+-- 0030    int PHI    0012  0024
+---- TRACE 1 stop -> loop
+
+---- TRACE 1 exit 0
+---- TRACE 1 exit 3
+--
+-- And the following after the patch:
+---- TRACE 1 IR
+-- ....        SNAP   #0   [ ---- ---- ---- ---- ---- ---- ---- ---- ---- ]
+-- 0001    u8  XLOAD  [0x102438521]  V
+-- 0002    int BAND   0001  +12
+-- 0003 >  int EQ     0002  +0
+-- 0004 >  int SLOAD  #8    T
+-- ....        SNAP   #1   [ ---- ---- ---- ---- ---- ---- ---- ---- ---- ]
+-- 0005 >  num SLOAD  #3    T
+-- 0006    num CONV   0004  num.int
+-- 0007  + num ADD    0006  0005
+-- 0008 >  fun SLOAD  #4    T
+-- 0009 >  tab SLOAD  #5    T
+-- 0010 >  int SLOAD  #6    T
+-- 0011 >  fun EQ     0008  ipairs_aux
+-- 0012  + int ADD    0010  +1
+-- 0013    int FLOAD  0009  tab.asize
+-- 0014 >  int ABC    0013  0012
+-- 0015    p64 FLOAD  0009  tab.array
+-- 0016    p64 AREF   0015  0012
+-- 0017 >+ num ALOAD  0016
+-- ....        SNAP   #2   [ ---- ---- ---- 0007 ---- ---- 0012 0012 0017 ]
+-- 0018 ------ LOOP ------------
+-- 0019    u8  XLOAD  [0x102438521]  V
+-- 0020    int BAND   0019  +12
+-- 0021 >  int EQ     0020  +0
+-- 0022 >  int CONV   0017  int.num
+-- ....        SNAP   #3   [ ---- ---- ---- 0007 ---- ---- 0012 0012 0017 ]
+-- 0023  + num ADD    0017  0007
+-- 0024  + int ADD    0012  +1
+-- 0025 >  int ABC    0013  0024
+-- 0026    p64 AREF   0015  0024
+-- 0027 >+ num ALOAD  0026
+-- 0028    num PHI    0017  0027
+-- 0029    num PHI    0007  0023
+-- 0030    int PHI    0012  0024
+---- TRACE 1 stop -> loop
+
+---- TRACE 1 exit 0
+---- TRACE 1 exit 2
+--
+-- Before the patch, the `0022 >  int CONV   0017  int.num`
+-- instruction is omitted due to DCE, which results in the
+-- third side exit being taken, instead of the second,
+-- and, hence, incorrect summation. After the patch, `CONV`
+-- is left intact and is not omitted; it remains as a guarded
+-- instruction, so the second side exit is taken and sum is
+-- performed correctly.
+
+for _, val in ipairs(data) do
+    if val == val then
+        sum = sum + val
+    end
+end
+
+test:ok(sum == sum, 'NaN check was not omitted')
+test:done(true)
--
2.39.3 (Apple Git-145)



More information about the Tarantool-patches mailing list