[PATCHv2 1/2] gdb/python: Reuse gdb.RegisterDescriptor objects where possible
Pedro Alves
pedro@palves.net
Wed Jul 22 13:10:17 GMT 2020
Hi Andrew,
Some nits below.
On 7/14/20 6:14 PM, Andrew Burgess wrote:
>
> +/* Token to access per-gdbarch data related to register descriptors. */
> +static struct gdbarch_data *gdbpy_register_object_data = NULL;
> +
> /* Structure for iterator over register descriptors. */
> typedef struct {
> PyObject_HEAD
> @@ -81,6 +84,17 @@ typedef struct {
> extern PyTypeObject reggroup_object_type
> CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("reggroup_object");
>
> +/* Associates a vector of gdb.RegisterDescriptor objects with GDBARCH as
> + gdbarch_data via the gdbarch post init registration mechanism
> + (gdbarch_data_register_post_init). */
> +
> +static void *
> +gdbpy_register_object_data_init (struct gdbarch *gdbarch)
> +{
> + std::vector<gdbpy_ref<>> *vec = new (std::vector<gdbpy_ref<>>);
> + return (void *) vec;
This could just be:
return new std::vector<gdbpy_ref<>>;
> +}
> +
> /* Create a new gdb.RegisterGroup object wrapping REGGROUP. */
>
> static PyObject *
> @@ -117,20 +131,38 @@ gdbpy_reggroup_name (PyObject *self, void *closure)
> return gdbpy_reggroup_to_string (self);
> }
>
> -/* Create an return a new gdb.RegisterDescriptor object. */
> -static PyObject *
> -gdbpy_new_register_descriptor (struct gdbarch *gdbarch,
> +/* Return a gdb.RegisterDescriptor object for REGNUM from GDBARCH. For
> + each REGNUM (in GDBARCH) only one descriptor is ever created, which is
> + then cached on the GDBARCH. */
> +
> +static gdbpy_ref<>
> +gdbpy_get_register_descriptor (struct gdbarch *gdbarch,
> int regnum)
> {
> - /* Create a new object and fill in its details. */
> - register_descriptor_object *reg
> - = PyObject_New (register_descriptor_object,
> - ®ister_descriptor_object_type);
> - if (reg == NULL)
> - return NULL;
> - reg->regnum = regnum;
> - reg->gdbarch = gdbarch;
> - return (PyObject *) reg;
> + auto vec = (std::vector<gdbpy_ref<>> *) gdbarch_data
> + (gdbarch, gdbpy_register_object_data);
Wrap the rhs in parens so the second line is properly aligned,
per the GNU standard's "so that emacs aligns it automatically"
rule:
auto vec = ((std::vector<gdbpy_ref<>> *) gdbarch_data
(gdbarch, gdbpy_register_object_data));
Or you could put the = in the next line, so that it aligns
without the parens:
auto vec
= (std::vector<gdbpy_ref<>> *) gdbarch_data (gdbarch,
gdbpy_register_object_data);
Note, I think it's more idiomatic to write the * for pointers:
auto *vec = ....
But since vec can't be NULL, I'd write a reference instead:
auto &vec
= *(std::vector<gdbpy_ref<>> *) gdbarch_data (gdbarch,
gdbpy_register_object_data);
> +
> + /* Ensure that we have enough entries in the vector. */
> + if (vec->size () <= regnum)
> + vec->resize ((regnum + 1), nullptr);
> +
> + /* If we don't already have a descriptor for REGNUM in GDBARCH then
> + create one now. */
> + if (vec->at (regnum) == nullptr)
Is there a reason you're using at? Was it to avoid
(*vec)[regnum]
or was it really about out-of-range errors?
If such as exception were thrown, it would be a logic
bug in GDB. And note that we don't catch it anywhere, so
it would bring down GDB.
There's a school of thought that claims that at should not
really exist, and I agree with it. :-)
If you go the reference route, then you can write the natural:
if (vec[regnum] = nullptr)
> + {
> + gdbpy_ref <register_descriptor_object> reg
> + (PyObject_New (register_descriptor_object,
> + ®ister_descriptor_object_type));
> + if (reg == NULL)
> + return NULL;
> + reg->regnum = regnum;
> + reg->gdbarch = gdbarch;
> + vec->at (regnum) = gdbpy_ref<> ((PyObject *) reg.release ());
> + }
> +
> + /* Grab the register descriptor from the vector, the reference count is
> + automatically incremented thanks to gdbpy_ref. */
> + return vec->at (regnum);
Ditto in these two other spots.
More information about the Gdb-patches
mailing list