Hi, Sergey!

Thanks for the review!

On 16.10.2026 15:54, Sergey Kaplun wrote:
Hi, Mikhail!
Thanks for the patch!
LGTM, after adding the comment for the testing snippet, see below.

On 16.10.26, Mikhail Elhimov wrote:
It has been copied by mistake from the LuaVela fork of LuaJIT.
---
Changes in v2:
  * Rebased onto https://lists.tarantool.org/pipermail/tarantool-patches/2026-October/030859.html to avoid conflicts

This patch is to be applied after https://lists.tarantool.org/pipermail/tarantool-patches/2026-October/030859.html

Branch: https://github.com/tarantool/luajit/tree/elhimov/gh-noticket-dbg-remove-wrong-gcstate

 src/luajit_dbg.py                             |  3 +-
 .../debug-extension-tests.py                  | 96 +++++++++++++++++--
 2 files changed, 87 insertions(+), 12 deletions(-)

diff --git a/src/luajit_dbg.py b/src/luajit_dbg.py
index a685ecfa..8f7249ab 100644
--- a/src/luajit_dbg.py
+++ b/src/luajit_dbg.py
<snipped>

diff --git a/test/tarantool-debugger-tests/debug-extension-tests.py b/test/tarantool-debugger-tests/debug-extension-tests.py
index bbd53dcc..735de2cb 100644
--- a/test/tarantool-debugger-tests/debug-extension-tests.py
+++ b/test/tarantool-debugger-tests/debug-extension-tests.py
<snipped>

+class TestGCStateBase(TestCaseBase):
+    extension_cmds = (
+        'lj-state\n'
+        'lj-gc\n'
+    )
+    lua_script = (
+        'local obj = newproxy(true)\n'
+        'getmetatable(obj).__gc = function() end\n'
+        'obj = nil\n'
+        'collectgarbage()\n'
+    )
It would be nice to add the comment here explaining why __all__ GC
states are reachable through this Lua code:
1) `gc_mark_start()` (GCpause) is always present in the full GC cycle.
2) `propagatemark()` (GCSpropagate) is reachable because our build has
   FFI and the finalizer table is marked as a weak table, i.e. it is
   grey. Hence, the g->gc.gray list is not empty.
3) `atomic()` (GCSatomic) is always present in the full GC cycle.
4) `gc_sweep_str_chain()` (GCSsweepstring) is always present in the full
   GC cycle.
5) `gc_sweep()` (GCSsweep) is always present in the full GC cycle.
6) `gc_finalize()` is met due to the finalizer to userdata in the
   script.
Done
+
+    @classmethod
+    def setUpClass(cls):
+        cls.pattern = (
+            compose_lj_state_rx(cls.gc_state) +
+            compose_gc_stats_rx(cls.gc_state)
+        )
+        super(TestGCStateBase, cls).setUpClass()
+
+
+class TestGCStatePause(TestGCStateBase):
+    gc_state = GCS_PAUSE
+    location = 'gc_mark_start'
+
+
+class TestGCStatePropagate(TestGCStateBase):
+    gc_state = GCS_PROPAGATE
+    location = 'propagatemark'
+
+
+class TestGCStateAtomic(TestGCStateBase):
+    gc_state = GCS_ATOMIC
+    location = 'atomic'
+
+
+class TestGCStateSweepString(TestGCStateBase):
+    gc_state = GCS_SWEEPSTRING
+    location = 'gc_sweep_str_chain'
+
+
+class TestGCStateSweep(TestGCStateBase):
+    gc_state = GCS_SWEEP
+    location = 'gc_sweep'
+
+
+class TestGCStateFinalize(TestGCStateBase):
+    gc_state = 'FINALIZE'
+    location = 'gc_finalize'
+
+
 STACK_RX = (
     r'-+ Red zone:\s+\d+ slots -+\n'
     r'(' + RX_ADDR + r'\s+' + RX_FRAME + r' VALUE: nil\n?)*\n'
-- 
2.43.0


    
-- 
Best regards,
Mikhail Elhimov