From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id C79D69A2C42; Tue, 12 Mar 2024 08:30:32 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org C79D69A2C42 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1710221432; bh=2Yqck7QsoASD2OqjIpJptcoaW2qhKRBxJ+MfJCvPtQ8=; h=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=p5DFfNSCJv3wHo84qCzMVo4xlwdvVX8mDB+s7em2laqARj2bqyxZ+N7CFxw0oCuX6 Sm0UIJCLTivvddL5wjyxZsosrcpPgvLp5onUUmn3At43Wso/NYQv54IwYJVYC32M1b GbcqIpp+aTuLhJo2ErvS4ux/0Ep35auqLzFdnOAk= Received: from smtp61.i.mail.ru (smtp61.i.mail.ru [95.163.41.99]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 8DF319A2C40 for ; Tue, 12 Mar 2024 08:30:31 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 8DF319A2C40 Received: by smtp61.i.mail.ru with esmtpa (envelope-from ) id 1rjuib-0000000GtmY-3Z4i; Tue, 12 Mar 2024 08:30:30 +0300 To: Maxim Kokryashkin , Sergey Bronnikov Date: Tue, 12 Mar 2024 08:26:27 +0300 Message-ID: <20240312052627.21222-1-skaplun@tarantool.org> X-Mailer: git-send-email 2.44.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Mailru-Src: smtp X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD987C0EE6E7F0A597DA4A6782E56D87B648E017E9626570F41182A05F538085040C96101E30F855683479CDAE959BF64248A29AC25A86224AADABE133367CC7B907F7399A604DAC192 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7364F8074C6DFACE2C2099A533E45F2D0395957E7521B51C2CFCAF695D4D8E9FCEA1F7E6F0F101C6778DA827A17800CE7A25B432396ED6D32EA1F7E6F0F101C6723150C8DA25C47586E58E00D9D99D84E1BDDB23E98D2D38B73AB1701401CD871DA82B427784B267D297A6F34DDCCFBD04BDAACDE8C64ABD7A471835C12D1D9774AD6D5ED66289B5278DA827A17800CE74A95F4E53E8DCE969FA2833FD35BB23D2EF20D2F80756B5F868A13BD56FB6657A471835C12D1D977725E5C173C3A84C327ED053E960B195E117882F4460429728AD0CFFFB425014E868A13BD56FB6657E2021AF6380DFAD1A18204E546F3947C2FFDA4F57982C5F42E808ACE2090B5E1725E5C173C3A84C3C5EA940A35A165FF2DBA43225CD8A89F616AD31D0D18CD5C57739F23D657EF2BB5C8C57E37DE458BEDA766A37F9254B7 X-C1DE0DAB: 0D63561A33F958A514DDA50E14BE67A95002B1117B3ED696BFD9226DBEF7F3FBB2920F75BA9A967F823CB91A9FED034534781492E4B8EEAD0BE004AA24E73514C79554A2A72441328621D336A7BC284946AD531847A6065A17B107DEF921CE79BDAD6C7F3747799A X-C8649E89: 1C3962B70DF3F0ADE00A9FD3E00BEEDF77DD89D51EBB7742D3581295AF09D3DF87807E0823442EA2ED31085941D9CD0AF7F820E7B07EA4CFEEDFA7CCEEDF6884C089204DA5F3093AA1687439E4E103523D75C6BEBA366E89F61CD9246542D0C4748ED927723DE83F1407385F205D77E58C4D3A303088C8FCEF78A38CDFD13943C226CC413062362A913E6812662D5F2A5EAB5682573093F7837F15F2B5E4A70B33F2C28C22F508233FCF178C6DD14203 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojWDseZ7hBpnh37oWNkE7s0Q== X-DA7885C5: 64EF3D68972E9BE5F255D290C0D534F962BC2992E462B3E8D985F7F28E68AD501022D7C100E958F05B1A4C17EAA7BC4BEF2421ABFA55128DAF83EF9164C44C7E X-Mailru-Sender: 689FA8AB762F7393590D8C940224AE337EAEAB0239D5A5CADF142A94939A2B87AF919DE58F2E453FE49D44BB4BD9522A059A1ED8796F048DB274557F927329BE89D5A3BC2B10C37545BD1C3CC395C826B4A721A3011E896F X-Mras: Ok Subject: [Tarantool-patches] [PATCH luajit] Check frame size limit before returning to a lower frame. X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Sergey Kaplun via Tarantool-patches Reply-To: Sergey Kaplun Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" From: Mike Pall Thanks to Sergey Kaplun. (cherry picked from commit 302366a33853b730f1b7eb61d792abc4f84f0caa) When compiling a stitched (or side) trace, there is no check for the frame size of the current prototype during recording. Hence, when we return (for example, after stitching) to the lower frame with a maximum possible frame size (249), the 251 = `baseslot` (2) + `maxslot` (249) slot for GC64 mode may be used. This leads to the corresponding assertion failure in `rec_check_slots()`. This patch adds the corresponding check. Sergey Kaplun: * added the description and the test for the problem Part of tarantool/tarantool#9595 --- Branch: https://github.com/tarantool/luajit/tree/skaplun/lj-1173-frame-limit-lower-frame Tarantool PR: https://github.com/tarantool/tarantool/pull/9791 Related issues: * https://github.com/tarantool/tarantool/issues/9595 * https://github.com/LuaJIT/LuaJIT/issues/1173 src/lj_record.c | 2 + .../lj-1173-frame-limit-lower-frame.test.lua | 83 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 test/tarantool-tests/lj-1173-frame-limit-lower-frame.test.lua diff --git a/src/lj_record.c b/src/lj_record.c index c01c1f0b..e3590b1a 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -886,6 +886,8 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) lj_trace_err(J, LJ_TRERR_LLEAVE); } else if (J->needsnap) { /* Tailcalled to ff with side-effects. */ lj_trace_err(J, LJ_TRERR_NYIRETL); /* No way to insert snapshot here. */ + } else if (1 + pt->framesize >= LJ_MAX_JSLOTS) { + lj_trace_err(J, LJ_TRERR_STACKOV); } else { /* Return to lower frame. Guard for the target we return to. */ TRef trpt = lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); TRef trpc = lj_ir_kptr(J, (void *)frame_pc(frame)); diff --git a/test/tarantool-tests/lj-1173-frame-limit-lower-frame.test.lua b/test/tarantool-tests/lj-1173-frame-limit-lower-frame.test.lua new file mode 100644 index 00000000..91e2c603 --- /dev/null +++ b/test/tarantool-tests/lj-1173-frame-limit-lower-frame.test.lua @@ -0,0 +1,83 @@ +local tap = require('tap') + +-- Test file to demonstrate LuaJIT assertion failure during +-- recording of side trace in GC64 mode with return to lower +-- frame, which has the maximum possible frame size. +-- See also: https://github.com/LuaJIT/LuaJIT/issues/1173. + +local test = tap.test('lj-1173-frame-limit-lower-frame'):skipcond({ + ['Test requires JIT enabled'] = not jit.status(), +}) + +test:plan(1) + +-- Parent trace with stitching and returning to a lower frame. +local function retf() + math.modf(1) +end +_G.retf = retf + +local LJ_MAX_JSLOTS = 250 + +-- Generate the following function: +-- | local uv = {key = 1} +-- | return function() +-- | local r = retf() +-- | uv.key, uv.key, --[[124 times in total ...]] uv.key = nil +-- | end +-- It will have the following bytecode: +-- | 0001 GGET 0 0 ; "retf" +-- | 0002 CALL 0 2 1 +-- | 0003 UGET 1 0 ; uv +-- | ... +-- | 0126 UGET 124 0 ; uv +-- | 0127 KNIL 125 248 +-- | 0128 TSETS 248 124 1 ; "key" +-- | ... +-- | 0251 TSETS 125 1 1 ; "key" +-- | 0252 RET0 0 1 +-- As you can see, the 249 slots (from 0 to 248) are occupied in +-- total. +-- When we return to the lower frame for the side trace, we may +-- hit the slot limit mentioned above: 2 slots are occupied +-- by the frame (`baseslot`) and `KNIL` bytecode recording sets +-- `maxslot` (the first free slot) to 249. Hence, the JIT slots +-- are overflowing. + +local chunk = 'local uv = {key = 1}\n' +chunk = chunk .. 'return function()\n' +chunk = chunk .. 'local r = retf()\n' + +-- Each `UGET` occupies 1 slot, `KNIL` occupies the same amount. +-- 1 slot is reserved (`r` variable), 1 pair is set outside the +-- cycle. 249 slots (the maximum available amount, see +-- , `bcreg_bump()` for details) are occupied in +-- total. +for _ = 1, LJ_MAX_JSLOTS / 2 - 2 do + chunk = chunk .. ('uv.key, ') +end +chunk = chunk .. 'uv.key = nil\n' +chunk = chunk .. 'end\n' + +local get_func = assert(loadstring(chunk)) +local function_max_framesize = get_func() + +jit.opt.start('hotloop=1', 'hotexit=1') + +-- Compile the parent trace first. +retf() +retf() + +-- Try to compile the side trace with a return to a lower frame +-- with a huge frame size. +function_max_framesize() +function_max_framesize() + +-- XXX: The limit check is OK with default defines for non-GC64 +-- mode, the trace is compiled for it. The test fails only with +-- GC64 mode enabled. Still run the test for non-GC64 mode to +-- avoid regressions. + +test:ok(true, 'no assertion failure during recording') + +test:done(true) -- 2.44.0