[RFC 7/9] gdb/python: convert gdb.Type to use gdbpy_registry

Jan Vrany
2025-01-27T10:48:38Z

This commit converts gdb.Type to use gdbpy_registry for lifecycle
management.
---
gdb/python/py-type.c | 117 ++++++-------------------------------------
1 file changed, 14 insertions(+), 103 deletions(-)

diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index c9fa6a37250..049cdca9a18 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -32,12 +32,6 @@ struct type_object
{
PyObject_HEAD
struct type *type;
-
- /* If a Type object is associated with an objfile, it is kept on a
- doubly-linked list, rooted in the objfile. This lets us copy the
- underlying struct type when the objfile is deleted. */
- struct type_object *prev;
- struct type_object *next;
};

extern PyTypeObject type_object_type
@@ -1166,120 +1160,44 @@ typy_richcompare (PyObject *self, PyObject *other, int op)
static void
set_type (type_object *obj, struct type *type);

-/* Deleter that saves types when an objfile is being destroyed. */
-struct typy_deleter_for_objfile_owned
+/* Invalidator that saves types when an objfile is being destroyed. */
+struct typy_invalidator
{
void operator() (type_object *obj)
{
- if (!gdb_python_initialized)
- return;
-
- /* This prevents another thread from freeing the objects we're
- operating on. */
- gdbpy_enter enter_py;
-
- copied_types_hash_t copied_types;
-
- while (obj)
+ if (obj->type->is_objfile_owned ())
{
- type_object *next = obj->next;
-
- copied_types.clear ();
+ copied_types_hash_t copied_types;

/* Set a copied (now arch-owned) type. As a side-effect this
adds OBJ to per-arch list. We do not need to remove it from
per-objfile list since the objfile is going to go completely
anyway. */
set_type (obj, copy_type_recursive (obj->type, copied_types));
-
- obj = next;
}
- }
-};
-
-/* Deleter that is used when an arch is is about to be freed. */
-struct typy_deleter_for_arch_owned
-{
- void operator() (type_object *obj)
- {
- while (obj)
+ else
{
- type_object *next = obj->next;
-
obj->type = nullptr;
-
- obj->next = nullptr;
- obj->prev = nullptr;
-
- obj = next;
}
}
};

-
-
-static const registry<objfile>::key<type_object, typy_deleter_for_objfile_owned>
- typy_objfile_data_key;
-static const registry<gdbarch>::key<type_object, typy_deleter_for_arch_owned>
- typy_gdbarch_data_key;
+static const gdbpy_registry<gdbpy_memoizing_registry_storage<type_object, type, &type_object::type, typy_invalidator>>
+ typy_registry;

static void
set_type (type_object *obj, struct type *type)
{
obj->type = type;
- obj->prev = nullptr;

/* Can it really happen that type is NULL? */
if (type != nullptr)
{
if (type->objfile_owner () != nullptr)
- {
- struct objfile *objfile = type->objfile_owner ();
-
- obj->next = typy_objfile_data_key.get (objfile);
- if (obj->next)
- obj->next->prev = obj;
- typy_objfile_data_key.set (objfile, obj);
- }
+ typy_registry.add (type->objfile_owner (), obj);
else
- {
- struct gdbarch *arch = type->arch_owner ();
-
- obj->next = typy_gdbarch_data_key.get (arch);
- if (obj->next)
- obj->next->prev = obj;
- typy_gdbarch_data_key.set (arch, obj);
- }
- }
- else
- obj->next = nullptr;
-}
-
-static void
-typy_dealloc (PyObject *obj)
-{
- type_object *type = (type_object *) obj;
-
- if (type->prev)
- type->prev->next = type->next;
- else if (type->type != nullptr)
- {
- if (type->type->is_objfile_owned ())
- {
- /* Must reset head of list. */
- struct objfile *objfile = type->type->objfile_owner ();
- typy_objfile_data_key.set (objfile, type->next);
- }
- else
- {
- struct gdbarch *arch = type->type->arch_owner ();
- typy_gdbarch_data_key.set (arch, type->next);
- }
+ typy_registry.add (type->arch_owner (), obj);
}
- if (type->next)
- type->next->prev = type->prev;
-
- Py_TYPE (type)->tp_free (type);
}

/* Return number of fields ("length" of the field dictionary). */
@@ -1525,19 +1443,12 @@ type_to_type_object (struct type *type)
/* Look if there's already a gdb.Type object for given TYPE
and if so, return it. */
if (type->is_objfile_owned ())
- type_obj = typy_objfile_data_key.get (type->objfile_owner ());
+ type_obj = typy_registry.lookup (type->objfile_owner (), type);
else
- type_obj = typy_gdbarch_data_key.get (type->arch_owner ());
+ type_obj = typy_registry.lookup (type->arch_owner (), type);

- while (type_obj != nullptr)
- {
- if (type_obj->type == type)
- {
- Py_INCREF (type_obj);
- return (PyObject*)type_obj;
- }
- type_obj = type_obj->next;
- }
+ if (type_obj != nullptr)
+ return (PyObject*)type_obj;

type_obj = PyObject_New (type_object, &type_object_type);
if (type_obj)
@@ -1750,7 +1661,7 @@ PyTypeObject type_object_type =
"gdb.Type", /*tp_name*/
sizeof (type_object), /*tp_basicsize*/
0, /*tp_itemsize*/
- typy_dealloc, /*tp_dealloc*/
+ 0, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
--
2.45.2