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 21D526ECE6; Wed, 30 Mar 2022 13:02:14 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 21D526ECE6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1648634534; bh=mvZtZ0BZFTe6H59dwwpN50MmF9bDo8tATcaZj+rrxAM=; h=Date:In-Reply-To:To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=dGw19KC/hFqXH/xb03CbBWeY1wbG8i/G0EtGpzSCOOtbXSAM2OW3a4VbuolWazG5v koFXQ436fHylPW7IFlcZgib1kK+4oHQAIjeGfJIZ1nuU1cu+U1z2HP5lGLjEXerhCP 7vTMTJLnyikLJKJOoLN6Iz2hGIkFP2yCRvq04v/k= Received: from smtp3.mail.ru (smtp3.mail.ru [94.100.179.58]) (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 1F8F76ECE6 for ; Wed, 30 Mar 2022 13:02:11 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 1F8F76ECE6 Received: by smtp3.mail.ru with esmtpa (envelope-from ) id 1nZV9W-0008GW-3M; Wed, 30 Mar 2022 13:02:10 +0300 Message-Id: Content-Type: multipart/alternative; boundary="Apple-Mail=_AF231DE9-E38B-4E20-A216-D69C476B42C3" Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.13\)) Date: Wed, 30 Mar 2022 13:02:08 +0300 In-Reply-To: To: Sergey Kaplun References: <20211022114653.4225-1-skaplun@tarantool.org> X-Mailer: Apple Mail (2.3654.120.0.1.13) X-4EC0790: 10 X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD92B0439D57C14BB619F76FA1B2E2E286FAC27582EB57AF1A700894C459B0CD1B9ABC689525FF3F8E98CDFD3072EE2126A9C7EA4E148CFBCC240D08F30CB48EA5E X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE718E10EF74DC9F9D0EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637369CDFF96C7994428638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D8BA200D667676008B8C13184B9CC10219117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCF1175FABE1C0F9B6A471835C12D1D9774AD6D5ED66289B52BA9C0B312567BB23117882F446042972877693876707352033AC447995A7AD18CB629EEF1311BF91D2E47CDBA5A96583BA9C0B312567BB231DD303D21008E29813377AFFFEAFD269A417C69337E82CC2E827F84554CEF50127C277FBC8AE2E8BA83251EDC214901ED5E8D9A59859A8B6D0C9BB9AE6BD5D69089D37D7C0E48F6C5571747095F342E88FB05168BE4CE3AF X-8FC586DF: 6EFBBC1D9D64D975 X-C1DE0DAB: 0D63561A33F958A5793F8762C5894EE89F8303BC997D4A040EF2C189705B16BAD59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA75FBC5FED0552DA851410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D344A431191C56981FE5B79336C25F688401BC2AC1904387C29844D2CEC3BE444DB4ECEB6C357D669A41D7E09C32AA3244C5483225857362D59ACD4DD76E68745E5853296C06374E602FACE5A9C96DEB163 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojlgoDDUY05+VlHIl4zq2FQw== X-Mailru-Sender: 3B9A0136629DC912F4AABCEFC589C81E51F010CBFEB5D54F476DA6C1721B594D0195CBD59DBDFA8CAD07DD1419AC565FA614486B47F28B67C5E079CCF3B0523AED31B7EB2E253A9EB0DAF586E7D11B3E67EA787935ED9F1B X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH luajit] Add missing LJ_MAX_JSLOTS check. 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: sergos via Tarantool-patches Reply-To: sergos Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" --Apple-Mail=_AF231DE9-E38B-4E20-A216-D69C476B42C3 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Hi! Thanks for updates! LGTM with a very small nit fix you=E2=80=99ve missed in the test = comment. Sergos > On 28 Mar 2022, at 13:02, Sergey Kaplun wrote: >=20 > Hi, Sergos! >=20 > Thanks for the review! >=20 > On 25.03.22, sergos wrote: >> Hi! >>=20 >> Thanks for the patch! >> Some nits in comments and I have exactly the same test result >> with and without the patch: >>=20 >> = root@dev1:/workspaces/t.sergos/third_party/luajit/test/tarantool-tests# = ../../src/luajit fix-slot-check-for-mm-record.test.lua=20 >> TAP version 13 >> 1..2 >> ok - nil >> ok - nil >>=20 >> for the reference - GC64 is off: >> = root@dev1:/workspaces/t.sergos/third_party/luajit/test/tarantool-tests# = ../../src/luajit -e "print(require('ffi').abi('gc64'))" >> false >=20 > Have you enabled assertions in debug build? >=20 My bad, now it fails w/o patch. thanks! > | $ ../../src/luajit fix-slot-check-for-mm-record.test.lua > | TAP version 13 > | 1..2 > | luajit: = /home/burii/builds_workspace/luajit/fix-slot-check-for-mm-record/src/lj_re= cord.c:92: rec_check_slots: Assertion `nslots < 250' failed. > | Aborted >=20 > I've done this as the following: > | $ cmake . -DCMAKE_BUILD_TYPE=3DDebug -DLUA_USE_APICHECK=3DON = -DLUA_USE_ASSERT=3DON -DLUAJIT_ENABLE_GC64=3DOFF && make -j >=20 >>=20 >> Regards, >> Sergos >>=20 >>> On 22 Oct 2021, at 14:46, Sergey Kaplun > wrote: >>>=20 >>> From: Mike Pall >=20 > I reformulated commit message as you suggested: >=20 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > Add missing LJ_MAX_JSLOTS check. >=20 > Thanks to Yichun Zhang. >=20 > (cherry picked from commit 630ff3196a06353c6a7ccd1e9ac3958f4a8ca13c) >=20 > JIT compiler doesn't check slots overflow for recording of metamethods > call. Slots limit (`LJ_MAX_JSLOTS` is 250) overflow assertion fails in > `rec_check_slots()` when we record metamethod call (`J->baseslot` diff = + > `J->maxslot` ~ 5-8 stack slots), while almost all slots of JIT engine > are occupied. >=20 > This patch adds the corresponding check in `lj_record_call()`. >=20 > Sergey Kaplun: > * added the description and the test for the problem >=20 > Part of tarantool/tarantool#6548 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >=20 > Branch is force pushed. >=20 >>>=20 >>> Thanks to Yichun Zhang. >>>=20 >>> (cherry picked from commit 630ff3196a06353c6a7ccd1e9ac3958f4a8ca13c) >>>=20 >>> Before the patch, JIT compiler doesn't check slots overflow for >>=20 >> Shall we put it like =E2=80=9Cbefore the patch=E2=80=9D? We=E2=80=99re = describing current behavior, >> which is apparently without the patch. Then we can use simple present = tense. >=20 > Fixed. >=20 >>=20 >>> recording of metamethods call. So the assertion in = `rec_check_slots()` >>> checking that we don't overflow the slots limit (the limit >>> `LJ_MAX_JSLOTS` is 250) is failing, >>=20 >> Slots limit overflow assertion fails in `rec_check_slots()` >=20 > Fixed. >=20 >>=20 >>> when we record metamethod call >>> (`J->baseslot` diff + `J->maxslot` ~ 5-8 stack slots), while almost = all >>> slots of JIT engine are occupied. >>>=20 >>=20 >> unlike the `lj_record_call()` (if I got it right?) during a = metamethod=20 >> recording. >=20 > We pass to `lj_record_call()` from any metamethod and this condition > isn't checked. >=20 >>=20 >>> This patch adds the corresponding check in `lj_record_call()`. >>>=20 >>> Sergey Kaplun: >>> * added the description and the test for the problem >>> --- >>>=20 >>> Tarantool branch: = https://github.com/tarantool/tarantool/tree/skaplun/gh-noticket-fix-slot-c= heck-for-mm-record >>> Branch: = https://github.com/tarantool/luajit/tree/skaplun/gh-noticket-fix-slot-chec= k-for-mm-record >>>=20 >>> src/lj_record.c | 2 + >>> .../fix-slot-check-for-mm-record.test.lua | 81 = +++++++++++++++++++ >>> 2 files changed, 83 insertions(+) >>> create mode 100644 = test/tarantool-tests/fix-slot-check-for-mm-record.test.lua >>>=20 >>> diff --git a/src/lj_record.c b/src/lj_record.c >>> index 42af09e5..adf2370e 100644 >>> --- a/src/lj_record.c >>> +++ b/src/lj_record.c >>> @@ -731,6 +731,8 @@ void lj_record_call(jit_State *J, BCReg func, = ptrdiff_t nargs) >>> J->framedepth++; >>> J->base +=3D func+1+LJ_FR2; >>> J->baseslot +=3D func+1+LJ_FR2; >>> + if (J->baseslot + J->maxslot >=3D LJ_MAX_JSLOTS) >>> + lj_trace_err(J, LJ_TRERR_STACKOV); >>> } >>>=20 >>> /* Record tail call. */ >>> diff --git = a/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua = b/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua >>> new file mode 100644 >>> index 00000000..e361830d >>> --- /dev/null >>> +++ b/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua >>> @@ -0,0 +1,81 @@ >>> +local tap =3D require('tap') >>> + >>> +local test =3D tap.test('fix-slot-check-for-mm-record') >>> +test:plan(2) >>> + >>> +-- Before the patch, JIT compiler doesn't check slots overflow >>> +-- for recording of metamethods call. So the assertion checking >>> +-- that we don't overflow the slots limit (the limit >>> +-- `LJ_MAX_JSLOTS` is 250) is failing, when we record metamethod >>> +-- call (`J->baseslot` diff + `J->maxslot` ~ 5-8 stack slots), >>> +-- while almost all slots of JIT engine are occupied. >>> + >>> +-- Table with the simplest metamethod to call. >>> +local a0 =3D setmetatable({}, { >>> + __add =3D function(t, arg1) >>> + t[arg1] =3D arg1 >>> + end >>> +}) >>> +_G.a0 =3D a0 >>> + >>> +-- Fixarg function with call to metamethod. >>> +local function a1() >>> + -- This constant is not setted as an upvalue to simplify stack >> ^^^^^^ set Didn=E2=80=99t mention in the update. Please, proceed. >>> + -- slots counting. Just remember that it is 42. >>> + return a0 + 42 >>> +end >>> +_G.a1 =3D a1 >>> + >>> +-- Generate bunch of functions to call them recursively. >>> +-- Each function is a vararg function bumps slots on >>> +-- 2 (4) =3D 1 (2) * 2 for usual Lua frame and vararg frame >>> +-- recording for GC32 (GC64). >>> +for i =3D 2, 121 do >>> + local f, err =3D load(('local r =3D a%d() return r'):format(i - = 1)) >>> + assert(f, err) >>> + _G['a'..i] =3D f >>> +end >>> + >>> +-- Trace is long enough, so we need to increase maxrecord. >>> +jit.opt.start('hotloop=3D1', 'maxrecord=3D2048') >>> + >>> +local function test_gc32() >>> + -- 1 - Base slot. >>> + -- 3 slots for cycle start, stop, step. >>> + for _ =3D 1, 4 do >>> + -- Occupy 1 slot for the function itself + 2 next slots will >>> + -- occupied for a call to the vararg function. >>> + -- Need 121 calls: 7 (baseslot after `a121()` is recorded) >>> + -- + 119 * 2 + 1 (`a1` -- is not vararg function) =3D 246 = slots. >>> + -- The next call of metamethod in `a0` to record have 2 args >>> + -- + 2 slots for metamethod function + 1 slot for frame. >>> + -- luacheck: no global >>> + a121() >>> + assert(a0[42] =3D=3D 42) >>> + a0[42] =3D nil >>> + end >>> + return true >>> +end >>> + >>> +local function test_gc64() >>> + -- 2 - Base slot. >>> + -- 3 slots for cycle start, stop, step. >>> + for _ =3D 1, 4 do >>> + -- Occupy 1 slot for the function itself + 4 next slots will >>> + -- occupied for a call to the vararg function. >>> + -- Need 60 calls: 10 (baseslot after `a60()` is recorded) >>> + -- + 58 * 4 + 2 (`a1` -- is not vararg function) =3D 244 slots. >>> + -- The next call of metamethod in `a0` to record have 2 args >>> + -- + 3 slots for metamethod function + 2 slots for frame. >>> + -- luacheck: no global >>> + a60() >>> + assert(a0[42] =3D=3D 42) >>> + a0[42] =3D nil >>> + end >>> + return true >>> +end >>> + >>> +test:ok(test_gc32()) >>> +test:ok(test_gc64()) >>> + >>> +os.exit(test:check() and 0 or 1) >>> --=20 >>> 2.31.0 >>>=20 >>=20 >=20 > --=20 > Best regards, > Sergey Kaplun --Apple-Mail=_AF231DE9-E38B-4E20-A216-D69C476B42C3 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8 Hi! = Thanks for updates!

LGTM with a very small nit fix you=E2=80=99ve missed in the = test comment.

Sergos


On 28 = Mar 2022, at 13:02, Sergey Kaplun <skaplun@tarantool.org> wrote:

Hi, Sergos!

Thanks for the review!

On 25.03.22, sergos wrote:
Hi!

Thanks= for the patch!
Some nits in comments and I have exactly = the same test result
with and without the patch:

root@dev1:/workspaces/t.sergos/third_party/luajit/test/tarantoo= l-tests# ../../src/luajit fix-slot-check-for-mm-record.test.lua 
TAP version = 13
1..2
ok - nil
ok - nil

for the reference - GC64 is off:
root@dev1:/workspaces/t.sergos/third_party/luajit/test/tarantoo= l-tests# ../../src/luajit -e "print(require('ffi').abi('gc64'))"
false

Have you enabled assertions in debug build?

My bad, now it fails w/o patch. = thanks!

| $ = ../../src/luajit fix-slot-check-for-mm-record.test.lua
| TAP version = 13
| = 1..2
| luajit: = /home/burii/builds_workspace/luajit/fix-slot-check-for-mm-record/src/lj_re= cord.c:92: rec_check_slots: Assertion `nslots < 250' = failed.
| = Aborted

I've done = this as the following:
| $ cmake . -DCMAKE_BUILD_TYPE=3DDebug -DLUA_USE_APICHECK=3DON = -DLUA_USE_ASSERT=3DON -DLUAJIT_ENABLE_GC64=3DOFF && make = -j


Regards,
Sergos

On 22 Oct 2021, at = 14:46, Sergey Kaplun <skaplun@tarantool.org> wrote:

From: Mike Pall <mike>

I reformulated commit message as you suggested:

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Add missing = LJ_MAX_JSLOTS check.

Thanks to Yichun Zhang.

(cherry picked from commit = 630ff3196a06353c6a7ccd1e9ac3958f4a8ca13c)

JIT compiler doesn't check slots overflow for recording of = metamethods
call. Slots = limit (`LJ_MAX_JSLOTS` is 250) overflow assertion fails in
`rec_check_slots()` when we record metamethod call = (`J->baseslot` diff +
`J->maxslot` ~ 5-8 stack slots), while almost all slots of = JIT engine
are = occupied.

This patch = adds the corresponding check in `lj_record_call()`.

Sergey = Kaplun:
* added the = description and the test for the problem

Part of tarantool/tarantool#6548
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

Branch is = force pushed.


Thanks to = Yichun Zhang.

(cherry picked from commit = 630ff3196a06353c6a7ccd1e9ac3958f4a8ca13c)

Before the patch, JIT compiler doesn't check slots overflow = for

Shall we put it like = =E2=80=9Cbefore the patch=E2=80=9D? We=E2=80=99re describing current = behavior,
which is apparently without the patch. Then we = can use simple present tense.

Fixed.


recording of metamethods call. So the assertion = in `rec_check_slots()`
checking that we don't overflow the = slots limit (the limit
`LJ_MAX_JSLOTS` is 250) is = failing,

Slots limit overflow = assertion fails in `rec_check_slots()`

Fixed.


when we record metamethod call
(`J->baseslot` diff + `J->maxslot` ~ 5-8 stack slots), = while almost all
slots of JIT engine are occupied.


unlike the = `lj_record_call()` (if I got it right?) during a metamethod 
recording.

We pass to `lj_record_call()` from any metamethod and this = condition
isn't = checked.


This patch adds the = corresponding check in `lj_record_call()`.

Sergey Kaplun:
* added the description and the = test for the problem
---

Tarantool branch: https://github.com/tarantool/tarantool/tree/skaplun/gh-noticket= -fix-slot-check-for-mm-record
Branch: https://github.com/tarantool/luajit/tree/skaplun/gh-noticket-fi= x-slot-check-for-mm-record

src/lj_record.c =             &n= bsp;           &nbs= p;     |  2 +
.../fix-slot-check-for-mm-record.test.lua =     | 81 +++++++++++++++++++
2 files = changed, 83 insertions(+)
create mode 100644 = test/tarantool-tests/fix-slot-check-for-mm-record.test.lua

diff --git a/src/lj_record.c = b/src/lj_record.c
index 42af09e5..adf2370e 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -731,6 +731,8 @@ void lj_record_call(jit_State *J, BCReg = func, ptrdiff_t nargs)
 J->framedepth++;
 J->base +=3D func+1+LJ_FR2;
 J->baseslot +=3D func+1+LJ_FR2;
+ =  if (J->baseslot + J->maxslot >=3D LJ_MAX_JSLOTS)
+    lj_trace_err(J, LJ_TRERR_STACKOV);
}

/* Record tail call. */
diff --git = a/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua = b/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua
new file mode 100644
index = 00000000..e361830d
--- /dev/null
+++ = b/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua
@@ -0,0 +1,81 @@
+local tap =3D = require('tap')
+
+local test =3D = tap.test('fix-slot-check-for-mm-record')
+test:plan(2)
+
+-- Before the patch, JIT compiler doesn't = check slots overflow
+-- for recording of metamethods = call. So the assertion checking
+-- that we don't overflow = the slots limit (the limit
+-- `LJ_MAX_JSLOTS` is 250) is = failing, when we record metamethod
+-- call = (`J->baseslot` diff + `J->maxslot` ~ 5-8 stack slots),
+-- while almost all slots of JIT engine are occupied.
+
+-- Table with the simplest metamethod to = call.
+local a0 =3D setmetatable({}, {
+ =  __add =3D function(t, arg1)
+ =    t[arg1] =3D arg1
+  end
+})
+_G.a0 =3D a0
+
+-- Fixarg function with call to metamethod.
+local function a1()
+  -- This constant = is not setted as an upvalue to simplify stack
        &n= bsp;           &nbs= p;       ^^^^^^ set

Didn=E2=80=99t mention in the update. Please, = proceed.

+  -- slots = counting. Just remember that it is 42.
+  return a0 + = 42
+end
+_G.a1 =3D a1
+
+-- Generate bunch of functions to call them recursively.
+-- Each function is a vararg function bumps slots on
+-- 2 (4) =3D 1 (2) * 2 for usual Lua frame and vararg = frame
+-- recording for GC32 (GC64).
+for i = =3D 2, 121 do
+  local f, err =3D load(('local r =3D = a%d() return r'):format(i - 1))
+  assert(f, err)
+  _G['a'..i] =3D f
+end
+
+-- Trace is long enough, so we need to increase = maxrecord.
+jit.opt.start('hotloop=3D1', = 'maxrecord=3D2048')
+
+local function = test_gc32()
+  -- 1 - Base slot.
+ =  -- 3 slots for cycle start, stop, step.
+  for = _ =3D 1, 4 do
+    -- Occupy 1 slot for the = function itself + 2 next slots will
+    -- = occupied for a call to the vararg function.
+ =    -- Need 121 calls: 7 (baseslot after `a121()` is = recorded)
+    -- + 119 * 2 + 1 (`a1` -- is = not vararg function) =3D 246 slots.
+    -- = The next call of metamethod in `a0` to record have 2 args
+ =    -- + 2 slots for metamethod function + 1 slot for = frame.
+    -- luacheck: no global
+    a121()
+ =    assert(a0[42] =3D=3D 42)
+ =    a0[42] =3D nil
+  end
+=  return true
+end
+
+local= function test_gc64()
+  -- 2 - Base slot.
+  -- 3 slots for cycle start, stop, step.
+=  for _ =3D 1, 4 do
+    -- Occupy 1 = slot for the function itself + 4 next slots will
+ =    -- occupied for a call to the vararg function.
+    -- Need 60 calls: 10 (baseslot after = `a60()` is recorded)
+    -- + 58 * 4 + 2 = (`a1` -- is not vararg function) =3D 244 slots.
+ =    -- The next call of metamethod in `a0` to record have = 2 args
+    -- + 3 slots for metamethod = function + 2 slots for frame.
+    -- = luacheck: no global
+    a60()
+    assert(a0[42] =3D=3D 42)
+ =    a0[42] =3D nil
+  end
+=  return true
+end
+
+test:ok(test_gc32())
+test:ok(test_gc64())
+
+os.exit(test:check() and 0 or 1)
-- 
2.31.0



-- Best = regards,
Sergey = Kaplun

= --Apple-Mail=_AF231DE9-E38B-4E20-A216-D69C476B42C3--