forked from LuaJIT/LuaJIT
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Mark CONV as non-weak, to prevent elimination of its side-effect.
An unused guarded CONV int.num cannot be omitted in general. (cherry-picked from commit 881d02d) 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#8825
- Loading branch information
1 parent
8e46d60
commit 68cc359
Showing
2 changed files
with
63 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
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=1', 'hotexit=1') | ||
|
||
-- 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 last trace is recorded, the traced bytecode | ||
-- is the following before the patch: | ||
-- ---- TRACE 4 start 2/3 test.lua:6 | ||
-- 0018 ADDVV 1 1 6 | ||
-- 0019 ITERC 5 3 3 | ||
-- 0000 . FUNCC ; ipairs_aux | ||
-- 0020 JITERL 5 1 | ||
-- 0021 GGET 2 7 ; "assert" | ||
-- 0022 ISEQV 1 1 | ||
-- 0023 JMP 4 => 0026 | ||
-- 0024 KPRI 4 1 | ||
-- 0025 JMP 5 => 0027 | ||
-- 0027 CALL 2 1 2 | ||
-- 0000 . FUNCC ; assert | ||
-- | ||
-- And the following after the patch: | ||
-- ---- TRACE 4 start 2/2 test.lua:5 | ||
-- 0016 ISNEV 6 6 | ||
-- 0017 JMP 7 => 0019 | ||
-- 0019 ITERC 5 3 3 | ||
-- 0000 . FUNCC ; ipairs_aux | ||
-- 0020 JITERL 5 1 | ||
-- 0021 GGET 2 7 ; "assert" | ||
-- 0022 ISEQV 1 1 | ||
-- 0023 JMP 4 => 0026 | ||
-- 0026 KPRI 4 2 | ||
-- 0027 CALL 2 1 2 | ||
-- 0000 . FUNCC ; assert | ||
-- 0028 RET0 0 1 | ||
-- | ||
-- The crucial difference here is the abscent | ||
-- `ISNEV` in the first case, which produces the | ||
-- desired guarded `CONV`, when translated to IR. | ||
-- | ||
-- Since there is no guard, NaN is added to the sum, | ||
-- despite the test case logic. | ||
|
||
for _, val in ipairs(data) do | ||
if val == val then | ||
sum = sum + val | ||
end | ||
end | ||
|
||
test:ok(sum == sum, 'NaN check was not omitted') | ||
|
||
os.exit(test:check() and 0 or 1) |