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 B004476E272; Fri, 12 Jan 2024 16:26:51 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org B004476E272 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1705066011; bh=s52Bqpcyp0T20O9ovKJdSvZ2k6O3PAwuTHeUYG/r/1k=; h=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=c+mK+00tnutcX1Q/ENLQakHY3m9M2VwSLWa+CsuY7fR+BvKmh3sL9uz74EuF/iAvS 9jSVs9J/+xt3ptIbCq39NuFFxKvCDlHkplrEcLuAgn8gm0XgQGOeIKBeWTqQGut+at vDsTIcvdf2evmrSz4tjb0xmaNL47UdRAwKNjDqJo= Received: from mail-lf1-f51.google.com (mail-lf1-f51.google.com [209.85.167.51]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 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 3EB267374C0 for ; Fri, 12 Jan 2024 16:26:50 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 3EB267374C0 Received: by mail-lf1-f51.google.com with SMTP id 2adb3069b0e04-50e741123acso7565814e87.0 for ; Fri, 12 Jan 2024 05:26:50 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705066009; x=1705670809; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=TAzjmw3Z8r2gmiogkX/lHt7tMc5ja6OI1mbcHgyVGuc=; b=nsf4gTiv7C0YAjOG3asRXPCvpajYwIOU3qeBW3pEjKeFewUpfI+LtiAgxXfaV9oevY 4J1NgFjgehUXNh4p7Ij7hMnOx36GOHtCoREfuAxetWQ6g3VRWfxlJ3pykiGfXoS+V0zp oXBTcWjAwmO7azT1SPxHFjqjT9bnMB9sMFMbTp9PTl+L90AX8pj0znH7GUKWVLk1a+VW ryrDdGDI8ggD/nou7tfbpQKHs4Ikkn154al8iJsrqTRFGF9Wd5+rVJfuHnUUHSvtFFBi SvgWS4o79Xas4Gz/N5Qkb/jIfA37NIgsF2Kh9eMvy4R1Zl6NO8kARK6uGfI7/vU58rO0 d6NQ== X-Gm-Message-State: AOJu0YzcyLRxHj2r2B0ek62LJvXsZyb+CNCqgOmMxd9LpoxTG04tEZlY rqbBU9GGJ4DM8uAbQm0bTPmQ9spg6U0= X-Google-Smtp-Source: AGHT+IHhDkqp02+mW5QoZs8rQ9ABlIf/lF6UAlr2dJeLt2+7KhalIIWdPKaOCbGC8Pjch46nfNM2fQ== X-Received: by 2002:ac2:5052:0:b0:50e:84f8:77dc with SMTP id a18-20020ac25052000000b0050e84f877dcmr608335lfm.111.1705066008253; Fri, 12 Jan 2024 05:26:48 -0800 (PST) Received: from localhost.localdomain ([2a00:1fa0:4a01:37c5:64af:ffa:a9ae:3427]) by smtp.gmail.com with ESMTPSA id x3-20020a056512078300b0050e7b033b77sm498332lfr.202.2024.01.12.05.26.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 Jan 2024 05:26:47 -0800 (PST) X-Google-Original-From: Maxim Kokryashkin To: tarantool-patches@dev.tarantool.org, skaplun@tarantool.org, sergeyb@tarantool.org Date: Fri, 12 Jan 2024 16:26:34 +0300 Message-ID: <20240112132643.106145-1-m.kokryashkin@tarantool.org> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH luajit] LJ_GC64: Fix HREFK optimization. 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: Maxim Kokryashkin via Tarantool-patches Reply-To: Maxim Kokryashkin Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" From: Mike Pall Contributed by XmiliaH. (cherry-picked from commit 91bc6b8ad1f373c1ce9003dc024b2e21fad0e444) In `lj_record_idx` when `ix->oldv` is the global nilnode and the required key is not present in the table, it is possible to pass the constant key lookup optimization condition because of the `uint32_t` overflow. Because of that, further recording incorrectly removes the check for the nilnode, which produces wrong results when trace is called for a different table. Maxim Kokryashkin: * added the description and the test for the problem Part of tarantool/tarantool#9145 --- Branch: https://github.com/tarantool/luajit/tree/fckxorg/lj-840-fix-hrefk-optimization PR: https://github.com/tarantool/tarantool/pull/9591 Issues: https://github.com/LuaJIT/LuaJIT/issues/840 https://github.com/tarantool/tarantool/issues/9145 src/lj_record.c | 8 +-- .../lj-840-fix-hrefk-optimization.test.lua | 58 +++++++++++++++++++ 2 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 test/tarantool-tests/lj-840-fix-hrefk-optimization.test.lua diff --git a/src/lj_record.c b/src/lj_record.c index a929b8aa..919e7169 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -1374,16 +1374,16 @@ static TRef rec_idx_key(jit_State *J, RecordIndex *ix, IRRef *rbref, key = emitir(IRTN(IR_CONV), key, IRCONV_NUM_INT); if (tref_isk(key)) { /* Optimize lookup of constant hash keys. */ - MSize hslot = (MSize)((char *)ix->oldv - (char *)&noderef(t->node)[0].val); - if (t->hmask > 0 && hslot <= t->hmask*(MSize)sizeof(Node) && - hslot <= 65535*(MSize)sizeof(Node)) { + GCSize hslot = (GCSize)((char *)ix->oldv-(char *)&noderef(t->node)[0].val); + if (hslot <= t->hmask*(GCSize)sizeof(Node) && + hslot <= 65535*(GCSize)sizeof(Node)) { TRef node, kslot, hm; *rbref = J->cur.nins; /* Mark possible rollback point. */ *rbguard = J->guardemit; hm = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_HMASK); emitir(IRTGI(IR_EQ), hm, lj_ir_kint(J, (int32_t)t->hmask)); node = emitir(IRT(IR_FLOAD, IRT_PGC), ix->tab, IRFL_TAB_NODE); - kslot = lj_ir_kslot(J, key, hslot / sizeof(Node)); + kslot = lj_ir_kslot(J, key, (IRRef)(hslot / sizeof(Node))); return emitir(IRTG(IR_HREFK, IRT_PGC), node, kslot); } } diff --git a/test/tarantool-tests/lj-840-fix-hrefk-optimization.test.lua b/test/tarantool-tests/lj-840-fix-hrefk-optimization.test.lua new file mode 100644 index 00000000..a11b91e3 --- /dev/null +++ b/test/tarantool-tests/lj-840-fix-hrefk-optimization.test.lua @@ -0,0 +1,58 @@ +local tap = require('tap') + +-- Test file to demonstrate incorrect HREFK optimization +-- in LuaJIT. + +local ffi = require('ffi') +local test = tap.test('lj-840-fix-hrefk-optimization'):skipcond({ + ['Test requires GC64 mode enabled'] = not ffi.abi('gc64'), + ['Test requires JIT enabled'] = not jit.status(), +}) +test:plan(1) + +local table_new = require('table.new') + +-- Size of single hash node in bytes. +local NODE_SIZE = 24 +-- Number of hash nodes to allocate on each iteration +-- based on the condition from `rec_idx_key` +local HASH_NODES = 65535 +-- The vector of hash nodes should have a raw size of +-- `HASH_NODES * NODE_SIZE`, which is allocated in +-- `lj_alloc_malloc` directly with `mmap`. However, +-- the LuaJIT allocator adds a bunch of small paddings +-- and aligns the required size to LJ_PAGESIZE, which is +-- 4096, so the actual allocated size includes alignment. +local ALIGNMENT = 4096 +-- The vector for hash nodes in the table is allocated based on +-- `hbits`, so it's actually got a size of 65536 nodes. +local SINGLE_ITERATION_ALLOC = (HASH_NODES + 1) * NODE_SIZE + ALIGNMENT + 72 +-- We need to overflow the 32-bit distance to the global nilnode, +-- so we divide 2^32 by the SINGLE_ITERATION_ALLOC. There are a +-- bunch of non-table.new allocations already performed, so one +-- iteration is subtracted to account for them. +local N_ITERATIONS = 0x100000000 / SINGLE_ITERATION_ALLOC - 1 +-- Prevent anchor table from interfering with target table allocations. +local anchor = table.new(N_ITERATIONS, 0) + +-- Construct table. +for _ = 1, N_ITERATIONS do + table.insert(anchor, table_new(0, HASH_NODES)) +end + +jit.opt.start('hotloop=1') +local function get_n(tab) + local x + for _ = 1, 4 do + x = tab.n + end + return x +end + +-- Record the trace for the constructed table. +get_n(anchor[#anchor]) + +-- Check the result for the table that has the required key. +local result = get_n({n=1}) +test:is(result, 1, 'correct value retrieved') +test:done(true) -- 2.43.0