Skip to content

Commit fe48a61

Browse files
Mike PallBuristan
Mike Pall
authored andcommitted
Fix recording of BC_VARG.
Reported by Bachir Bendrissou. (cherry picked from commit 62e362a) When the trace is started after the stitching, it may not have some slots from the first one. That slot may be the first slot given to the `select()` function (if it is determined by the call that caused the stitch). Before the patch, there is no loading of this slot in the `rec_varg()` for the trace, and the 0 value from slots is taken instead. Hence, the following recording of `BC_VARG` is incorrect. This patch fixes this by using the `getslot()` instead of taking the value directly. Sergey Kaplun: * added the description and the test for the problem Part of tarantool/tarantool#11055
1 parent e0c8208 commit fe48a61

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

src/lj_record.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1869,7 +1869,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
18691869
J->maxslot = dst + (BCReg)nresults;
18701870
}
18711871
} else if (select_detect(J)) { /* y = select(x, ...) */
1872-
TRef tridx = J->base[dst-1];
1872+
TRef tridx = getslot(J, dst-1);
18731873
TRef tr = TREF_NIL;
18741874
ptrdiff_t idx = lj_ffrecord_select_mode(J, tridx, &J->L->base[dst-1]);
18751875
if (idx < 0) goto nyivarg;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
local tap = require('tap')
2+
3+
-- Test file to demonstrate incorrect recording of `BC_VARG` that
4+
-- is given to the `select()` function. See also:
5+
-- https://www.freelists.org/post/luajit/Possible-issue-during-register-allocation-ra-alloc1.
6+
7+
local test = tap.test('fix-recording-bc-varg-used-in-select'):skipcond({
8+
['Test requires JIT enabled'] = not jit.status(),
9+
})
10+
11+
test:plan(1)
12+
13+
-- XXX: Simplify `jit.dump` output.
14+
local modf = math.modf
15+
16+
local EXPECTED = 'canary'
17+
local function test_func(...)
18+
local first_varg_item
19+
for _ = 1, 4 do
20+
-- `modf()` is used to create a stitching with a meaningful
21+
-- index value, that equals 1, i.e. refers to the first item
22+
-- in `...`. The second trace started after stitching does not
23+
-- contain the stack slot for the first argument of the
24+
-- `select()`. Before the patch, there is no loading of
25+
-- this slot for the trace and the 0 value is taken instead.
26+
-- Hence, this leads to an incorrect recording of the
27+
-- `BC_VARG` with detected `select()`.
28+
first_varg_item = select(modf(1, 0), ...)
29+
end
30+
return first_varg_item
31+
end
32+
33+
jit.opt.start('hotloop=1')
34+
test:is(test_func(EXPECTED), EXPECTED, 'corect BC_VARG recording')
35+
36+
test:done(true)

0 commit comments

Comments
 (0)