* [Tarantool-patches] [PATCH luajit] dbg: remove wrong GC state
@ 2026-10-15 7:20 Mikhail Elhimov via Tarantool-patches
2026-10-15 23:45 ` [Tarantool-patches] [PATCH luajit v2] " Mikhail Elhimov via Tarantool-patches
0 siblings, 1 reply; 6+ messages in thread
From: Mikhail Elhimov via Tarantool-patches @ 2026-10-15 7:20 UTC (permalink / raw)
To: Sergey Kaplun, Sergey Bronnikov, Evgeniy Temirgaleev; +Cc: tarantool-patches
It was copied originally by mistake from the LuaVela fork of LuaJIT.
---
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 1d553fb9..4ee2e70e 100644
--- a/src/luajit_dbg.py
+++ b/src/luajit_dbg.py
@@ -1246,7 +1246,6 @@ def gc_state(g):
3: 'SWEEPSTRING',
4: 'SWEEP',
5: 'FINALIZE',
- 6: 'LAST',
}.get(int(g['gc']['state']), 'INVALID')
@@ -2841,7 +2840,7 @@ class LJState(dbg.LJBase):
lj-state
The command requires no args and dumps current VM and GC states:
* VM state: <INTERP|C|GC|EXIT|RECORD|OPT|ASM|TRACE>
-* GC state: <PAUSE|PROPAGATE|ATOMIC|SWEEPSTRING|SWEEP|FINALIZE|LAST>
+* GC state: <PAUSE|PROPAGATE|ATOMIC|SWEEPSTRING|SWEEP|FINALIZE>
* JIT state: <IDLE|ACTIVE|RECORD|START|END|ASM|ERR>
'''
diff --git a/test/tarantool-debugger-tests/debug-extension-tests.py b/test/tarantool-debugger-tests/debug-extension-tests.py
index b6e51185..8456dde9 100644
--- a/test/tarantool-debugger-tests/debug-extension-tests.py
+++ b/test/tarantool-debugger-tests/debug-extension-tests.py
@@ -133,6 +133,23 @@ elif machine == 'arm64' or machine == 'aarch64':
else:
raise Exception('Unknown architecture in testing')
+GCS_PAUSE = 'PAUSE'
+GCS_PROPAGATE = 'PROPAGATE'
+GCS_ATOMIC = 'ATOMIC'
+GCS_SWEEPSTRING = 'SWEEPSTRING'
+GCS_SWEEP = 'SWEEP'
+GCS_FINALIZE = 'FINALIZE'
+
+RX_VALID_GC_STATES = r'({})'.format('|'.join([
+ GCS_PAUSE,
+ GCS_PROPAGATE,
+ GCS_ATOMIC,
+ GCS_SWEEPSTRING,
+ GCS_SWEEP,
+ GCS_FINALIZE,
+]))
+RX_INVALID_GC_STATE = r'INVALID'
+
class TestCaseBase(unittest.TestCase):
@classmethod
@@ -269,23 +286,24 @@ class TestLJArch(TestCaseBase):
)
-class TestLJState(TestCaseBase):
- extension_cmds = 'lj-state'
- location = 'lj_cf_print'
- lua_script = 'print(1)'
- pattern = (
+def compose_lj_state_rx(rx_gc_state):
+ return (
r'VM state: [A-Z]+\n'
- r'GC state: [A-Z]+\n'
+ r'GC state: ' + rx_gc_state + '\n'
r'JIT state: [A-Z]+\n'
)
-class TestLJGC(TestCaseBase):
- extension_cmds = 'lj-gc'
+class TestLJState(TestCaseBase):
+ extension_cmds = 'lj-state'
location = 'lj_cf_print'
lua_script = 'print(1)'
- pattern = (
- r'GC stats: [A-Z]+\n'
+ pattern = compose_lj_state_rx(RX_VALID_GC_STATES)
+
+
+def compose_gc_stats_rx(rx_gc_state):
+ return (
+ r'GC stats: ' + rx_gc_state + '\n'
r'\ttotal: \d+\n'
r'\tthreshold: \d+\n'
r'\tdebt: \d+\n'
@@ -301,6 +319,64 @@ class TestLJGC(TestCaseBase):
)
+class TestLJGC(TestCaseBase):
+ extension_cmds = 'lj-gc'
+ location = 'lj_cf_print'
+ lua_script = 'print(1)'
+ pattern = compose_gc_stats_rx(RX_VALID_GC_STATES)
+
+
+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'
+ )
+
+ @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
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Tarantool-patches] [PATCH luajit v2] dbg: remove wrong GC state
2026-10-15 7:20 [Tarantool-patches] [PATCH luajit] dbg: remove wrong GC state Mikhail Elhimov via Tarantool-patches
@ 2026-10-15 23:45 ` Mikhail Elhimov via Tarantool-patches
2026-10-16 12:54 ` Sergey Kaplun via Tarantool-patches
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Mikhail Elhimov via Tarantool-patches @ 2026-10-15 23:45 UTC (permalink / raw)
To: Sergey Kaplun, Sergey Bronnikov, Evgeniy Temirgaleev; +Cc: tarantool-patches
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
@@ -1244,7 +1244,6 @@ def gc_state(g):
3: 'SWEEPSTRING',
4: 'SWEEP',
5: 'FINALIZE',
- 6: 'LAST',
}.get(int(g['gc']['state']), 'INVALID')
@@ -2850,7 +2849,7 @@ LJState.__doc__ = '''
lj-state
The command requires no args and dumps current VM and GC states:
* VM state: <{}>
-* GC state: <PAUSE|PROPAGATE|ATOMIC|SWEEPSTRING|SWEEP|FINALIZE|LAST>
+* GC state: <PAUSE|PROPAGATE|ATOMIC|SWEEPSTRING|SWEEP|FINALIZE>
* JIT state: <IDLE|ACTIVE|RECORD|START|END|ASM|ERR>
'''.format('|'.join(VM_STATES))
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
@@ -133,6 +133,23 @@ elif machine == 'arm64' or machine == 'aarch64':
else:
raise Exception('Unknown architecture in testing')
+GCS_PAUSE = 'PAUSE'
+GCS_PROPAGATE = 'PROPAGATE'
+GCS_ATOMIC = 'ATOMIC'
+GCS_SWEEPSTRING = 'SWEEPSTRING'
+GCS_SWEEP = 'SWEEP'
+GCS_FINALIZE = 'FINALIZE'
+
+RX_VALID_GC_STATES = r'({})'.format('|'.join([
+ GCS_PAUSE,
+ GCS_PROPAGATE,
+ GCS_ATOMIC,
+ GCS_SWEEPSTRING,
+ GCS_SWEEP,
+ GCS_FINALIZE,
+]))
+RX_INVALID_GC_STATE = r'INVALID'
+
class TestCaseBase(unittest.TestCase):
@classmethod
@@ -283,23 +300,24 @@ RX_VM_STATE = '({})'.format('|'.join([
]))
-class TestLJState(TestCaseBase):
- extension_cmds = 'lj-state'
- location = 'lj_cf_print'
- lua_script = 'print(1)'
- pattern = (
+def compose_lj_state_rx(rx_gc_state):
+ return (
r'VM state: ' + RX_VM_STATE + '\n'
- r'GC state: [A-Z]+\n'
+ r'GC state: ' + rx_gc_state + '\n'
r'JIT state: [A-Z]+\n'
)
-class TestLJGC(TestCaseBase):
- extension_cmds = 'lj-gc'
+class TestLJState(TestCaseBase):
+ extension_cmds = 'lj-state'
location = 'lj_cf_print'
lua_script = 'print(1)'
- pattern = (
- r'GC stats: [A-Z]+\n'
+ pattern = compose_lj_state_rx(RX_VALID_GC_STATES)
+
+
+def compose_gc_stats_rx(rx_gc_state):
+ return (
+ r'GC stats: ' + rx_gc_state + '\n'
r'\ttotal: \d+\n'
r'\tthreshold: \d+\n'
r'\tdebt: \d+\n'
@@ -315,6 +333,64 @@ class TestLJGC(TestCaseBase):
)
+class TestLJGC(TestCaseBase):
+ extension_cmds = 'lj-gc'
+ location = 'lj_cf_print'
+ lua_script = 'print(1)'
+ pattern = compose_gc_stats_rx(RX_VALID_GC_STATES)
+
+
+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'
+ )
+
+ @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
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Tarantool-patches] [PATCH luajit v2] dbg: remove wrong GC state
2026-10-15 23:45 ` [Tarantool-patches] [PATCH luajit v2] " Mikhail Elhimov via Tarantool-patches
@ 2026-10-16 12:54 ` Sergey Kaplun via Tarantool-patches
2026-10-17 8:39 ` Mikhail Elhimov via Tarantool-patches
2026-10-16 14:49 ` Sergey Bronnikov via Tarantool-patches
2026-10-17 8:32 ` [Tarantool-patches] [PATCH luajit v3] " Mikhail Elhimov via Tarantool-patches
2 siblings, 1 reply; 6+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2026-10-16 12:54 UTC (permalink / raw)
To: Mikhail Elhimov; +Cc: tarantool-patches
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.
> +
> + @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,
Sergey Kaplun
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Tarantool-patches] [PATCH luajit v2] dbg: remove wrong GC state
2026-10-15 23:45 ` [Tarantool-patches] [PATCH luajit v2] " Mikhail Elhimov via Tarantool-patches
2026-10-16 12:54 ` Sergey Kaplun via Tarantool-patches
@ 2026-10-16 14:49 ` Sergey Bronnikov via Tarantool-patches
2026-10-17 8:32 ` [Tarantool-patches] [PATCH luajit v3] " Mikhail Elhimov via Tarantool-patches
2 siblings, 0 replies; 6+ messages in thread
From: Sergey Bronnikov via Tarantool-patches @ 2026-10-16 14:49 UTC (permalink / raw)
To: Mikhail Elhimov, Sergey Kaplun, Evgeniy Temirgaleev; +Cc: tarantool-patches
Hi, Mikhail,
thanks for the patch! LGTM
Sergey
On 10/16/26 02:45, 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
> @@ -1244,7 +1244,6 @@ def gc_state(g):
> 3: 'SWEEPSTRING',
> 4: 'SWEEP',
> 5: 'FINALIZE',
> - 6: 'LAST',
> }.get(int(g['gc']['state']), 'INVALID')
>
>
> @@ -2850,7 +2849,7 @@ LJState.__doc__ = '''
> lj-state
> The command requires no args and dumps current VM and GC states:
> * VM state: <{}>
> -* GC state: <PAUSE|PROPAGATE|ATOMIC|SWEEPSTRING|SWEEP|FINALIZE|LAST>
> +* GC state: <PAUSE|PROPAGATE|ATOMIC|SWEEPSTRING|SWEEP|FINALIZE>
> * JIT state: <IDLE|ACTIVE|RECORD|START|END|ASM|ERR>
> '''.format('|'.join(VM_STATES))
>
> 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
> @@ -133,6 +133,23 @@ elif machine == 'arm64' or machine == 'aarch64':
> else:
> raise Exception('Unknown architecture in testing')
>
> +GCS_PAUSE = 'PAUSE'
> +GCS_PROPAGATE = 'PROPAGATE'
> +GCS_ATOMIC = 'ATOMIC'
> +GCS_SWEEPSTRING = 'SWEEPSTRING'
> +GCS_SWEEP = 'SWEEP'
> +GCS_FINALIZE = 'FINALIZE'
> +
> +RX_VALID_GC_STATES = r'({})'.format('|'.join([
> + GCS_PAUSE,
> + GCS_PROPAGATE,
> + GCS_ATOMIC,
> + GCS_SWEEPSTRING,
> + GCS_SWEEP,
> + GCS_FINALIZE,
> +]))
> +RX_INVALID_GC_STATE = r'INVALID'
> +
>
> class TestCaseBase(unittest.TestCase):
> @classmethod
> @@ -283,23 +300,24 @@ RX_VM_STATE = '({})'.format('|'.join([
> ]))
>
>
> -class TestLJState(TestCaseBase):
> - extension_cmds = 'lj-state'
> - location = 'lj_cf_print'
> - lua_script = 'print(1)'
> - pattern = (
> +def compose_lj_state_rx(rx_gc_state):
> + return (
> r'VM state: ' + RX_VM_STATE + '\n'
> - r'GC state: [A-Z]+\n'
> + r'GC state: ' + rx_gc_state + '\n'
> r'JIT state: [A-Z]+\n'
> )
>
>
> -class TestLJGC(TestCaseBase):
> - extension_cmds = 'lj-gc'
> +class TestLJState(TestCaseBase):
> + extension_cmds = 'lj-state'
> location = 'lj_cf_print'
> lua_script = 'print(1)'
> - pattern = (
> - r'GC stats: [A-Z]+\n'
> + pattern = compose_lj_state_rx(RX_VALID_GC_STATES)
> +
> +
> +def compose_gc_stats_rx(rx_gc_state):
> + return (
> + r'GC stats: ' + rx_gc_state + '\n'
> r'\ttotal: \d+\n'
> r'\tthreshold: \d+\n'
> r'\tdebt: \d+\n'
> @@ -315,6 +333,64 @@ class TestLJGC(TestCaseBase):
> )
>
>
> +class TestLJGC(TestCaseBase):
> + extension_cmds = 'lj-gc'
> + location = 'lj_cf_print'
> + lua_script = 'print(1)'
> + pattern = compose_gc_stats_rx(RX_VALID_GC_STATES)
> +
> +
> +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'
> + )
> +
> + @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'
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Tarantool-patches] [PATCH luajit v3] dbg: remove wrong GC state
2026-10-15 23:45 ` [Tarantool-patches] [PATCH luajit v2] " Mikhail Elhimov via Tarantool-patches
2026-10-16 12:54 ` Sergey Kaplun via Tarantool-patches
2026-10-16 14:49 ` Sergey Bronnikov via Tarantool-patches
@ 2026-10-17 8:32 ` Mikhail Elhimov via Tarantool-patches
2 siblings, 0 replies; 6+ messages in thread
From: Mikhail Elhimov via Tarantool-patches @ 2026-10-17 8:32 UTC (permalink / raw)
To: Sergey Kaplun, Sergey Bronnikov, Evgeniy Temirgaleev; +Cc: tarantool-patches
It was copied originally by mistake from the LuaVela fork of LuaJIT.
---
Changes in v3:
* Added comment about reachability of all the GC states from the same lua script
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 | 113 ++++++++++++++++--
2 files changed, 104 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
@@ -1244,7 +1244,6 @@ def gc_state(g):
3: 'SWEEPSTRING',
4: 'SWEEP',
5: 'FINALIZE',
- 6: 'LAST',
}.get(int(g['gc']['state']), 'INVALID')
@@ -2850,7 +2849,7 @@ LJState.__doc__ = '''
lj-state
The command requires no args and dumps current VM and GC states:
* VM state: <{}>
-* GC state: <PAUSE|PROPAGATE|ATOMIC|SWEEPSTRING|SWEEP|FINALIZE|LAST>
+* GC state: <PAUSE|PROPAGATE|ATOMIC|SWEEPSTRING|SWEEP|FINALIZE>
* JIT state: <IDLE|ACTIVE|RECORD|START|END|ASM|ERR>
'''.format('|'.join(VM_STATES))
diff --git a/test/tarantool-debugger-tests/debug-extension-tests.py b/test/tarantool-debugger-tests/debug-extension-tests.py
index bbd53dcc..9b6484ca 100644
--- a/test/tarantool-debugger-tests/debug-extension-tests.py
+++ b/test/tarantool-debugger-tests/debug-extension-tests.py
@@ -133,6 +133,23 @@ elif machine == 'arm64' or machine == 'aarch64':
else:
raise Exception('Unknown architecture in testing')
+GCS_PAUSE = 'PAUSE'
+GCS_PROPAGATE = 'PROPAGATE'
+GCS_ATOMIC = 'ATOMIC'
+GCS_SWEEPSTRING = 'SWEEPSTRING'
+GCS_SWEEP = 'SWEEP'
+GCS_FINALIZE = 'FINALIZE'
+
+RX_VALID_GC_STATES = r'({})'.format('|'.join([
+ GCS_PAUSE,
+ GCS_PROPAGATE,
+ GCS_ATOMIC,
+ GCS_SWEEPSTRING,
+ GCS_SWEEP,
+ GCS_FINALIZE,
+]))
+RX_INVALID_GC_STATE = r'INVALID'
+
class TestCaseBase(unittest.TestCase):
@classmethod
@@ -283,23 +300,24 @@ RX_VM_STATE = '({})'.format('|'.join([
]))
-class TestLJState(TestCaseBase):
- extension_cmds = 'lj-state'
- location = 'lj_cf_print'
- lua_script = 'print(1)'
- pattern = (
+def compose_lj_state_rx(rx_gc_state):
+ return (
r'VM state: ' + RX_VM_STATE + '\n'
- r'GC state: [A-Z]+\n'
+ r'GC state: ' + rx_gc_state + '\n'
r'JIT state: [A-Z]+\n'
)
-class TestLJGC(TestCaseBase):
- extension_cmds = 'lj-gc'
+class TestLJState(TestCaseBase):
+ extension_cmds = 'lj-state'
location = 'lj_cf_print'
lua_script = 'print(1)'
- pattern = (
- r'GC stats: [A-Z]+\n'
+ pattern = compose_lj_state_rx(RX_VALID_GC_STATES)
+
+
+def compose_gc_stats_rx(rx_gc_state):
+ return (
+ r'GC stats: ' + rx_gc_state + '\n'
r'\ttotal: \d+\n'
r'\tthreshold: \d+\n'
r'\tdebt: \d+\n'
@@ -315,6 +333,81 @@ class TestLJGC(TestCaseBase):
)
+class TestLJGC(TestCaseBase):
+ extension_cmds = 'lj-gc'
+ location = 'lj_cf_print'
+ lua_script = 'print(1)'
+ pattern = compose_gc_stats_rx(RX_VALID_GC_STATES)
+
+
+class TestGCStateBase(TestCaseBase):
+ extension_cmds = (
+ 'lj-state\n'
+ 'lj-gc\n'
+ )
+
+ # The same lua code is used to check all the GC states because
+ # it allows to reach any of them:
+ # 1) `gc_mark_start()` (PAUSE) is always present in the full
+ # GC cycle.
+ # 2) `propagatemark()` (PROPAGATE) is reachable because our
+ # build has FFI and the finalizer table is marked as a weak
+ # table, i.e. it is gray. Hence, the g->gc.gray list is not
+ # empty.
+ # 3) `atomic()` (ATOMIC) is always present in the full GC
+ # cycle.
+ # 4) `gc_sweep_str_chain()` (SWEEPSTRING) is always present in
+ # the full GC cycle.
+ # 5) `gc_sweep()` (SWEEP) is always present in the full GC
+ # cycle.
+ # 6) `gc_finalize()` (FINALIZE) is met due to the finalizer to
+ # userdata in the script.
+ lua_script = (
+ 'local obj = newproxy(true)\n'
+ 'getmetatable(obj).__gc = function() end\n'
+ 'obj = nil\n'
+ 'collectgarbage()\n'
+ )
+
+ @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 = GCS_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
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Tarantool-patches] [PATCH luajit v2] dbg: remove wrong GC state
2026-10-16 12:54 ` Sergey Kaplun via Tarantool-patches
@ 2026-10-17 8:39 ` Mikhail Elhimov via Tarantool-patches
0 siblings, 0 replies; 6+ messages in thread
From: Mikhail Elhimov via Tarantool-patches @ 2026-10-17 8:39 UTC (permalink / raw)
To: Sergey Kaplun; +Cc: tarantool-patches
[-- Attachment #1: Type: text/plain, Size: 3507 bytes --]
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 ontohttps://lists.tarantool.org/pipermail/tarantool-patches/2026-October/030859.html to avoid conflicts
>>
>> This patch is to be applied afterhttps://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'-+ Redzone:\s+\d+ slots -+\n'
>> r'(' + RX_ADDR + r'\s+' + RX_FRAME + r' VALUE: nil\n?)*\n'
>> --
>> 2.43.0
>>
--
Best regards,
Mikhail Elhimov
[-- Attachment #2: Type: text/html, Size: 4810 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-17 8:39 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-15 7:20 [Tarantool-patches] [PATCH luajit] dbg: remove wrong GC state Mikhail Elhimov via Tarantool-patches
2026-10-15 23:45 ` [Tarantool-patches] [PATCH luajit v2] " Mikhail Elhimov via Tarantool-patches
2026-10-16 12:54 ` Sergey Kaplun via Tarantool-patches
2026-10-17 8:39 ` Mikhail Elhimov via Tarantool-patches
2026-10-16 14:49 ` Sergey Bronnikov via Tarantool-patches
2026-10-17 8:32 ` [Tarantool-patches] [PATCH luajit v3] " Mikhail Elhimov via Tarantool-patches
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox