Tarantool development patches archive
 help / color / mirror / Atom feed
From: Mikhail Elhimov via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: Sergey Kaplun <skaplun@tarantool.org>,
	Sergey Bronnikov <sergeyb@tarantool.org>,
	Evgeniy Temirgaleev <e.temirgaleev@tarantool.org>
Cc: tarantool-patches@dev.tarantool.org
Subject: [Tarantool-patches] [PATCH luajit] dbg: avoid hardcoded vmstate
Date: Wed, 14 Oct 2026 18:02:48 +0300	[thread overview]
Message-ID: <20261014150248.296106-1-m.elhimov@vk.team> (raw)

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'
     )
-- 
2.43.0


                 reply	other threads:[~2026-10-14 15:02 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261014150248.296106-1-m.elhimov@vk.team \
    --to=tarantool-patches@dev.tarantool.org \
    --cc=e.temirgaleev@tarantool.org \
    --cc=m.elhimov@vk.team \
    --cc=sergeyb@tarantool.org \
    --cc=skaplun@tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH luajit] dbg: avoid hardcoded vmstate' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox