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 65F816EC55; Mon, 19 Jul 2021 10:37:51 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 65F816EC55 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1626680271; bh=4rE/d7qGa+FaEInJXGP+TTUTcL25rAiaS0yL64T8KuM=; h=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=jFw5l62VCnyeVre01GIoBqsFm+pxYD78sG+CkjpHvTlgQSLG3MeuzhLXEI/of4fRC cASjzs9Oc2oX0MhTO/TuHAKjEiWjH3ZsiK/DDt98lPoxQdm+OL65F7lhzouWJzK2GA KBrFB9ZZZMPJC7PMzVd7RKJ49++9ijGWxqwJpu4A= Received: from smtp34.i.mail.ru (smtp34.i.mail.ru [94.100.177.94]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id C39756EC55 for ; Mon, 19 Jul 2021 10:37:49 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org C39756EC55 Received: by smtp34.i.mail.ru with esmtpa (envelope-from ) id 1m5NqW-00040L-FR; Mon, 19 Jul 2021 10:37:48 +0300 To: Igor Munkin , Sergey Ostanevich Date: Mon, 19 Jul 2021 10:36:32 +0300 Message-Id: <20210719073632.12008-1-skaplun@tarantool.org> X-Mailer: git-send-email 2.31.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD941C43E597735A9C3038391AAE5FBFA76FBCFDED1455B43CD182A05F5380850409D2EF3E04D173E2F7DC7A0570067E6C13135145ABD750320431EEB0003C8DB6C X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7AEA4A6B3AFC9B957C2099A533E45F2D0395957E7521B51C2CFCAF695D4D8E9FCEA1F7E6F0F101C6778DA827A17800CE78A0D58E4FC2FF961EA1F7E6F0F101C6723150C8DA25C47586E58E00D9D99D84E1BDDB23E98D2D38BBCA57AF85F7723F2F9E80F416AE102C37993E5375DE908DDCC7F00164DA146DAFE8445B8C89999728AA50765F790063773DCDF0198120BE8389733CBF5DBD5E9C8A9BA7A39EFB766F5D81C698A659EA7CC7F00164DA146DA9985D098DBDEAEC8457EE4B4996FC546F6B57BC7E6449061A352F6E88A58FB86F5D81C698A659EA7E827F84554CEF5019E625A9149C048EE9ECD01F8117BC8BEE2021AF6380DFAD18AA50765F790063735872C767BF85DA227C277FBC8AE2E8BC6A536F79815AD9275ECD9A6C639B01B4E70A05D1297E1BBCB5012B2E24CD356 X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975CBC3D6B4D9834ECA7C8F94646BEB85AFA9622639909701EA19C2B6934AE262D3EE7EAB7254005DCED2972A488E2682F5992E1F3B950BCE21616EB5DE968479BF5B2CF3E77A3BD9B2CBDC6A1CF3F042BAD6DF99611D93F60EF8CC5112E3E56BCDB699F904B3F4130E343918A1A30D5E7FCCB5012B2E24CD356 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34D041FB2E16F174C4FF7A7F482E21E4BF9155778BEE7540ECB1455B52A4B7B9779BBBC952BDFF1C5B1D7E09C32AA3244C0183E43EAEAA918EE731D6645E37E1A0A95CA90A1D8AC565927AC6DF5659F194 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2bioj+8+KVR9NZrHvMqzW4/ZgvQ== X-Mailru-Sender: 3B9A0136629DC91206CBC582EFEF4CB450A522903067A14A873F61B65A42F8D81261A09626DB84A2F2400F607609286E924004A7DEC283833C7120B22964430C52B393F8C72A41A89437F6177E88F7363CDA0F3B3F5B9367 X-Mras: Ok Subject: [Tarantool-patches] [PATCH luajit] Fix bytecode register allocation for comparisons. 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 (cherry picked from commit 2f3f07882fb4ad9c64967d7088461b1ca0a25d3a) When LuaJIT is build with LJ_FR2 (GC64), information about frame takes two slots -- the first takes the TValue with the function to call, the second takes the additional frame information. The recording JIT machinery works pretty the same -- the function IR_KGC is loaded in the first slot, and the second is set to TREF_FRAME value. This value should be rewritten after return from a callee. It is done either by the return values either this slot is cleared (set to zero) manually with the next bytecode with RA dst mode with the assumption, that the dst RA takes the next slot after TREF_FRAME, i.e. an earlier instruction uses the smallest possible destination register (see `lj_record_ins()` for the details). Bytecode allocator swaps operands for ISGT and ISGE comparisons. When it happens, the aforementioned rule for registers allocations may be violated. When it happens, and this chunk is recording, the slot with TREF_FRAME is not rewritten (but the next empty slot after TREF_FRAME is) during bytecode recording. This leads to JIT slots inconsistency and assertion failure in `rec_check_slots()` during recording the next bytecode instruction. This patch fixes bytecode register allocation by changing the register allocation order in case of ISGT and ISGE bytecodes. Sergey Kaplun: * added the description and the test for the problem Resolves tarantool/tarantool#6227 --- Branch: https://github.com/tarantool/luajit/tree/skaplun/gh-6227-fix-bytecode-allocator-for-comp Tarantool branch: https://github.com/tarantool/tarantool/tree/skaplun/gh-6227-fix-bytecode-allocator-for-comp Issue: https://github.com/tarantool/tarantool/issues/6227 src/lj_parse.c | 7 +++- ...ytecode-allocator-for-comparisons.test.lua | 41 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 test/tarantool-tests/gh-6227-bytecode-allocator-for-comparisons.test.lua diff --git a/src/lj_parse.c b/src/lj_parse.c index 08f7cfa6..a6325a76 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c @@ -853,9 +853,12 @@ static void bcemit_comp(FuncState *fs, BinOpr opr, ExpDesc *e1, ExpDesc *e2) e1 = e2; e2 = eret; /* Swap operands. */ op = ((op-BC_ISLT)^3)+BC_ISLT; expr_toval(fs, e1); + ra = expr_toanyreg(fs, e1); + rd = expr_toanyreg(fs, e2); + } else { + rd = expr_toanyreg(fs, e2); + ra = expr_toanyreg(fs, e1); } - rd = expr_toanyreg(fs, e2); - ra = expr_toanyreg(fs, e1); ins = BCINS_AD(op, ra, rd); } /* Using expr_free might cause asserts if the order is wrong. */ diff --git a/test/tarantool-tests/gh-6227-bytecode-allocator-for-comparisons.test.lua b/test/tarantool-tests/gh-6227-bytecode-allocator-for-comparisons.test.lua new file mode 100644 index 00000000..66f6885e --- /dev/null +++ b/test/tarantool-tests/gh-6227-bytecode-allocator-for-comparisons.test.lua @@ -0,0 +1,41 @@ +local tap = require('tap') +local test = tap.test('gh-6227-bytecode-allocator-for-comparisons') +test:plan(1) + +-- Test file to demonstrate assertion failure during recording +-- wrong allocated bytecode for comparisons. +-- See also https://github.com/tarantool/tarantool/issues/6227. + +-- Need function with RET0 bytecode to avoid reset of +-- the first JIT slot with frame info. Also need no assignments +-- by the caller. +local function empty() end + +local uv = 0 + +-- This function needs to reset register enumerating. +-- Also set `J->maxslot` to zero. +-- The upvalue function to call is loaded to 0 slot. +local function bump_frame() + -- First call function with RET0 to set TREF_FRAME in the + -- last slot. + empty() + -- Test ISGE or ISGT bytecode. These bytecodes swap their + -- operands. Also, a constant is always loaded into the slot + -- smaller than upvalue. So, if upvalue loads before KSHORT, + -- then the difference between registers is more than 2 (2 is + -- needed for LJ_FR2) and TREF_FRAME slot is not rewriting by + -- the bytecode after call and return as expected. That leads + -- to recording slots inconsistency and assertion failure at + -- `rec_check_slots()`. + empty(1>uv) +end + +jit.opt.start('hotloop=1') + +for _ = 1,3 do + bump_frame() +end + +test:ok(true) +os.exit(test:check() and 0 or 1) -- 2.31.0