[Tarantool-patches] [PATCH luajit] dbg: avoid hardcoded vmstate

Mikhail Elhimov m.elhimov at vk.team
Fri Oct 16 01:53:25 MSK 2026


This patch is closed (it has been integrated into 
https://lists.tarantool.org/pipermail/tarantool-patches/2026-October/030858.html)

On 14.10.2026 18:02, Mikhail Elhimov wrote:
> Follows-up f0897ba86494b250512be18e25bafccffadb27b1 ("dbg: avoid
> hardcoded enums (get them from target)").
>
> Also tests were adjusted to use stricter regex for vm state.
> ---
> Branch: https://github.com/tarantool/luajit/tree/elhimov/gh-13094-dbg-avoid-hardcoded-vmstate
> Related issues: https://github.com/tarantool/tarantool/issues/13094
>
>   src/luajit_dbg.py                             | 88 +++++++++----------
>   .../debug-extension-tests.py                  | 16 +++-
>   2 files changed, 58 insertions(+), 46 deletions(-)
>
> diff --git a/src/luajit_dbg.py b/src/luajit_dbg.py
> index 7c2d085f..e0b8f958 100644
> --- a/src/luajit_dbg.py
> +++ b/src/luajit_dbg.py
> @@ -198,7 +198,7 @@ class Debugger(object):
>       # different in GDB and LLDB, so this method is needed to hide
>       # the implementation details.
>       @abc.abstractmethod
> -    def create_enum_value(self, enum_name, enum_member_name):
> +    def create_enum_value(self, enum_member_name, enum_name=None):
>           '''Return debugger-specific value object that represents
>           the given enum member.
>           '''
> @@ -357,7 +357,7 @@ class _GDBDebugger(Debugger):
>       def register_command(self, command, name):
>           command(name)
>   
> -    def create_enum_value(self, enum_name, enum_member_name):
> +    def create_enum_value(self, enum_member_name, enum_name):
>           val = self.eval(enum_member_name)
>           assert val.type.code == gdb.TYPE_CODE_ENUM
>           return val
> @@ -752,27 +752,31 @@ class _LLDBDebugger(Debugger):
>               )
>           )
>   
> -    def create_enum_value(self, enum_name, enum_member_name):
> -        # In LLDB an enum member has to be specified in the form:
> -        # <enum_name>::<enum_member_name>
> -        val = self.eval(enum_name + "::" + enum_member_name)
> -        # Be aware that SBValue.IsValid() is necessary, but not
> -        # sufficient as it only indicates that the object does
> -        # contain the relevant data (including potential error),
> -        # so it is necessary to check additionally that no error
> -        # has occurred while evaluating the expression.
> -        if val.sbvalue.IsValid() and val.sbvalue.error.Success():
> -            assert self._lldb_tp_isenum(val.sbvalue.GetType())
> -            return val
> -
> -        # LLDB uses the enum name in the expression above but
> -        # debugging information about the enum name might be
> -        # optimized out if no variable of the given enum type is
> -        # declared and its members are only used as the predefined
> -        # constants (like in case of the enum IRFieldID).
> -
> -        # In this case the above method doesn't work so trying to
> -        # discover the enum type by the given enum member.
> +    def create_enum_value(self, enum_member_name, enum_name):
> +        if enum_name is not None:
> +            # In LLDB an enum member has to be specified in the
> +            # form: <enum_name>::<enum_member_name>
> +            val = self.eval(enum_name + "::" + enum_member_name)
> +            # Be aware that SBValue.IsValid() is necessary, but
> +            # not sufficient as it only indicates that the object
> +            # does contain the relevant data (including potential
> +            # error), so it is necessary to check additionally
> +            # that no error has occurred while evaluating the
> +            # expression.
> +            if val.sbvalue.IsValid() and val.sbvalue.error.Success():
> +                assert self._lldb_tp_isenum(val.sbvalue.GetType())
> +                return val
> +
> +        # LLDB needs the enum name in the expression above but
> +        # 1. Enum might be anonymous (like LJ_VMST__MAX)
> +        # 2. Debugging information about the enum name might be
> +        #    optimized out if no variable of the given enum type
> +        #    is declared and its members are only used as the
> +        #    predefined constants (like in case of the enum
> +        #    IRFieldID)
> +
> +        # In these cases the above method doesn't work so trying
> +        # to discover the enum type by the given enum member.
>   
>           def find_enum_type_member(enum_type, enum_member_name):
>               # SBTypeEnumMemberList supports members iteration and
> @@ -870,10 +874,10 @@ def strx64(val):
>   
>   
>   class EnumBasedList(object):
> -    def __init__(self, enum_name, max_enum_member, map_func=None,
> +    def __init__(self, max_enum_member, enum_name, map_func=None,
>                    *map_func_extra_args):
> -        self.__enum_name = enum_name
>           self.__max_enum_member = max_enum_member
> +        self.__enum_name = enum_name
>           self.__map_func = map_func
>           self.__map_func_extra_args = map_func_extra_args
>           # Lazy initialization (see __get_items) as the required
> @@ -892,7 +896,7 @@ class EnumBasedList(object):
>       def __get_items(self):
>           if self.__items is None:
>               max_enum_value = dbg.create_enum_value(
> -                self.__enum_name, self.__max_enum_member
> +                self.__max_enum_member, self.__enum_name
>               )
>               items = []
>               for i in range(max_enum_value):
> @@ -985,7 +989,7 @@ def bc_d(ins):
>       return int(ins) >> 16
>   
>   
> -BCMODE = EnumBasedList('BCMode', 'BCM_max', cut_prefix, 'BCM')
> +BCMODE = EnumBasedList('BCM_max', 'BCMode', cut_prefix, 'BCM')
>   
>   
>   lj_bc_mode_ = None
> @@ -1011,7 +1015,7 @@ def bcmode_cd(op):
>       return int((lj_bc_mode()[op] >> 7) & 15)
>   
>   
> -BYTECODES = EnumBasedList('BCOp', 'BC__MAX', cut_prefix, 'BC_')
> +BYTECODES = EnumBasedList('BC__MAX', 'BCOp', cut_prefix, 'BC_')
>   
>   
>   def proto_bc(proto):
> @@ -1166,7 +1170,7 @@ def J(g):
>   
>   
>   # Matched `MMDEF(_)`.
> -MM_NAMES = EnumBasedList('MMS', 'MM__MAX', cut_prefix, 'MM_')
> +MM_NAMES = EnumBasedList('MM__MAX', 'MMS', cut_prefix, 'MM_')
>   
>   
>   # Get the name of the index in the predefined arrays.
> @@ -1219,18 +1223,12 @@ def ggfname_by_offset(offset):
>       return ggfname
>   
>   
> +VM_STATES = EnumBasedList('LJ_VMST__MAX', None, cut_prefix, 'LJ_VMST_')
> +
> +
>   def vm_state(g):
> -    return {
> -        i2notu32(0): 'INTERP',
> -        i2notu32(1): 'LFUNC',
> -        i2notu32(2): 'FFUNC',
> -        i2notu32(3): 'CFUNC',
> -        i2notu32(4): 'GC',
> -        i2notu32(5): 'EXIT',
> -        i2notu32(6): 'RECORD',
> -        i2notu32(7): 'OPT',
> -        i2notu32(8): 'ASM',
> -    }.get(int(tou32(g['vmstate'])), 'TRACE')
> +    index = i2notu32(g['vmstate'])
> +    return VM_STATES[index] if index < len(VM_STATES) else 'TRACE'
>   
>   
>   def gc_state(g):
> @@ -1427,7 +1425,7 @@ def cdataptr(cd):
>   # JIT engine.
>   
>   
> -IRS = EnumBasedList('IROp', 'IR__MAX', cut_prefix, 'IR_')
> +IRS = EnumBasedList('IR__MAX', 'IROp', cut_prefix, 'IR_')
>   
>   
>   # Mode bits: Commutative, {Normal/Ref, Alloc, Load, Store},
> @@ -1479,7 +1477,7 @@ def ir_mode(op):
>       return mode
>   
>   
> -IRTYPES = EnumBasedList('IRType', 'IRT__MAX', lambda x: {
> +IRTYPES = EnumBasedList('IRT__MAX', 'IRType', lambda x: {
>                               'IRT_CDATA': 'cdt',
>                               'IRT_FLOAT': 'flt',
>                               'IRT_LIGHTUD': 'lud',
> @@ -1488,11 +1486,11 @@ IRTYPES = EnumBasedList('IRType', 'IRT__MAX', lambda x: {
>                           }.get(x, cut_prefix(x, 'IRT_')[:3].ljust(3).lower()))
>   
>   
> -IRFIELDS = EnumBasedList('IRFieldID', 'IRFL__MAX', lambda x:
> +IRFIELDS = EnumBasedList('IRFL__MAX', 'IRFieldID', lambda x:
>                            cut_prefix(x, 'IRFL_').lower().replace('_', '.', 1))
>   
>   
> -IRFPMS = EnumBasedList('IRFPMathOp', 'IRFPM__MAX',
> +IRFPMS = EnumBasedList('IRFPM__MAX', 'IRFPMathOp',
>                          lambda x: cut_prefix(x, 'IRFPM_').lower())
>   
>   
> @@ -1522,7 +1520,7 @@ REGISTERS = {
>   }
>   
>   
> -IR_CALLS = EnumBasedList('IRCallID', 'IRCALL__MAX', cut_prefix, 'IRCALL_')
> +IR_CALLS = EnumBasedList('IRCALL__MAX', 'IRCallID', cut_prefix, 'IRCALL_')
>   
>   
>   def regname(reg_number):
> diff --git a/test/tarantool-debugger-tests/debug-extension-tests.py b/test/tarantool-debugger-tests/debug-extension-tests.py
> index 5e369f00..359163e9 100644
> --- a/test/tarantool-debugger-tests/debug-extension-tests.py
> +++ b/test/tarantool-debugger-tests/debug-extension-tests.py
> @@ -262,12 +262,26 @@ class TestLJArch(TestCaseBase):
>       )
>   
>   
> +RX_VM_STATE = '({})'.format('|'.join([
> +    'INTERP',
> +    'LFUNC',
> +    'FFUNC',
> +    'CFUNC',
> +    'GC',
> +    'EXIT',
> +    'RECORD',
> +    'OPT',
> +    'ASM',
> +    'TRACE',
> +]))
> +
> +
>   class TestLJState(TestCaseBase):
>       extension_cmds = 'lj-state'
>       location = 'lj_cf_print'
>       lua_script = 'print(1)'
>       pattern = (
> -        r'VM state: [A-Z]+\n'
> +        r'VM state: ' + RX_VM_STATE + '\n'
>           r'GC state: [A-Z]+\n'
>           r'JIT state: [A-Z]+\n'
>       )

-- 
Best regards,
Mikhail Elhimov



More information about the Tarantool-patches mailing list