From: Andrew Burgess <andrew.burgess@embecosm.com>
To: gdb-patches@sourceware.org
Cc: Tom Tromey <tom@tromey.com>,
Andrew Burgess <andrew.burgess@embecosm.com>
Subject: [PATCHv2 1/2] gdb/python: Reuse gdb.RegisterDescriptor objects where possible
Date: Tue, 14 Jul 2020 18:14:30 +0100 [thread overview]
Message-ID: <c79440bcf9ea71e9887a7b3d04177f98aabc38b8.1594746770.git.andrew.burgess@embecosm.com> (raw)
In-Reply-To: <cover.1594746770.git.andrew.burgess@embecosm.com>
Instead of having the gdb.RegisterDescriptorIterator creating new
gdb.RegisterDescriptor objects for each regnum, instead cache
gdb.RegisterDescriptor objects on the gdbarch object and reuse these.
This means that for every gdbarch/regnum pair there is a single unique
gdb.RegisterDescriptor, this feels like a neater implementation than
the existing one.
It is possible for a user to see (in Python code) that the descriptors
are now identical, but as the descriptors are read-only this should
make no real difference.
There should be no other user visible changes.
gdb/ChangeLog:
* python/py-registers.c (gdbpy_register_object_data): New static
global.
(gdbpy_register_object_data_init): New function.
(gdbpy_new_register_descriptor): Renamed to...
(gdbpy_get_register_descriptor): ...this, and update to reuse
existing register descriptors where possible.
(gdbpy_register_descriptor_iter_next): Update.
(gdbpy_initialize_registers): Register new gdbarch data.
gdb/testsuite/ChangeLog:
* gdb.python/py-arch-reg-names.exp: Additional tests.
---
gdb/ChangeLog | 11 ++++
gdb/python/py-registers.c | 61 +++++++++++++++----
gdb/testsuite/ChangeLog | 4 ++
.../gdb.python/py-arch-reg-names.exp | 19 ++++++
4 files changed, 82 insertions(+), 13 deletions(-)
diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c
index db0fe37eecb..8e22a919d87 100644
--- a/gdb/python/py-registers.c
+++ b/gdb/python/py-registers.c
@@ -24,6 +24,9 @@
#include "reggroups.h"
#include "python-internal.h"
+/* 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;
+}
+
/* 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);
+
+ /* 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)
+ {
+ 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);
}
/* Convert the register descriptor to a string. */
@@ -281,7 +313,7 @@ gdbpy_register_descriptor_iter_next (PyObject *self)
iter_obj->regnum++;
if (name != nullptr && *name != '\0')
- return gdbpy_new_register_descriptor (gdbarch, regnum);
+ return gdbpy_get_register_descriptor (gdbarch, regnum).release ();
}
while (true);
}
@@ -291,6 +323,9 @@ gdbpy_register_descriptor_iter_next (PyObject *self)
int
gdbpy_initialize_registers ()
{
+ gdbpy_register_object_data
+ = gdbarch_data_register_post_init (gdbpy_register_object_data_init);
+
register_descriptor_object_type.tp_new = PyType_GenericNew;
if (PyType_Ready (®ister_descriptor_object_type) < 0)
return -1;
diff --git a/gdb/testsuite/gdb.python/py-arch-reg-names.exp b/gdb/testsuite/gdb.python/py-arch-reg-names.exp
index 14bc0a822a4..8dd34ef5fd2 100644
--- a/gdb/testsuite/gdb.python/py-arch-reg-names.exp
+++ b/gdb/testsuite/gdb.python/py-arch-reg-names.exp
@@ -85,3 +85,22 @@ for { set i 0 } { $i < [llength $regs] } { incr i } {
}
}
gdb_assert { $found_non_match == 0 } "all registers match"
+
+# Check that we get the same register descriptors from two different
+# iterators.
+gdb_py_test_silent_cmd \
+ "python iter1 = arch.registers ()" \
+ "get first all register iterator" 0
+gdb_py_test_silent_cmd \
+ "python iter2 = arch.registers ()" \
+ "get second all register iterator" 0
+gdb_py_test_silent_cmd \
+ [multi_line_input \
+ "python" \
+ "for r1, r2 in zip(iter1, iter2):" \
+ " if (r1.name != r2.name):"\
+ " raise gdb.GdbError (\"miss-matched names\")" \
+ " if (r1 != r2):" \
+ " raise gdb.GdbError (\"miss-matched objects\")" \
+ "\004" ] \
+ "check names and objects match" 1
--
2.25.4
next prev parent reply other threads:[~2020-07-14 17:14 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-08 8:48 [PATCH 0/2] Improvements to Python Register Descriptor API Andrew Burgess
2020-07-08 8:48 ` [PATCH 1/2] gdb/python: Reuse gdb.RegisterDescriptor objects where possible Andrew Burgess
2020-07-13 18:21 ` Tom Tromey
2020-07-08 8:48 ` [PATCH 2/2] gdb/python: Reuse gdb.RegisterGroup " Andrew Burgess
2020-07-13 18:23 ` Tom Tromey
2020-07-14 17:14 ` [PATCHv2 0/2] Improvements to Python Register Descriptor API Andrew Burgess
2020-07-14 17:14 ` Andrew Burgess [this message]
2020-07-22 13:10 ` [PATCHv2 1/2] gdb/python: Reuse gdb.RegisterDescriptor objects where possible Pedro Alves
2020-07-22 14:05 ` Andrew Burgess
2020-07-22 14:32 ` Pedro Alves
2020-07-22 15:10 ` Andrew Burgess
2020-07-14 17:14 ` [PATCHv2 2/2] gdb/python: Reuse gdb.RegisterGroup " Andrew Burgess
2020-07-21 18:26 ` [PATCHv2 0/2] Improvements to Python Register Descriptor API Tom Tromey
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=c79440bcf9ea71e9887a7b3d04177f98aabc38b8.1594746770.git.andrew.burgess@embecosm.com \
--to=andrew.burgess@embecosm.com \
--cc=gdb-patches@sourceware.org \
--cc=tom@tromey.com \
/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
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox