diff options
author | Andrew Burgess <andrew.burgess@embecosm.com> | 2020-07-07 15:26:42 +0100 |
---|---|---|
committer | Andrew Burgess <andrew.burgess@embecosm.com> | 2020-07-21 21:57:08 +0100 |
commit | baf8791efb4b5cb41348b11ad9f63e6c2a004c5f (patch) | |
tree | 87b92e4e11919ae60839e352c79c4833b5f8a58c /gdb/python | |
parent | f7306dac19c502232f766c3881313857915f330d (diff) | |
download | fsf-binutils-gdb-baf8791efb4b5cb41348b11ad9f63e6c2a004c5f.zip fsf-binutils-gdb-baf8791efb4b5cb41348b11ad9f63e6c2a004c5f.tar.gz fsf-binutils-gdb-baf8791efb4b5cb41348b11ad9f63e6c2a004c5f.tar.bz2 |
gdb/python: Reuse gdb.RegisterGroup objects where possible
Only create one gdb.RegisterGroup Python object for each of GDB's
reggroup objects.
I could have added a field into the reggroup object to hold the Python
object pointer for each reggroup, however, as reggroups are never
deleted within GDB, and are global (not per-architecture) a simpler
solution seemed to be just to hold a single global map from reggroup
pointer to a Python object representing the reggroup. Then we can
reuse the objects out of this map.
After this commit it is possible for a user to tell that two
gdb.RegisterGroup objects are now identical when previously they were
unique, however, as both these objects are read-only I don't think
this should be a problem.
There should be no other user visible changes after this commit.
gdb/ChangeLog:
* python/py-registers.c : Add 'unordered_map' include.
(gdbpy_new_reggroup): Renamed to...
(gdbpy_get_reggroup): ...this. Update to only create register
group descriptors when needed.
(gdbpy_reggroup_iter_next): Update.
gdb/testsuite/ChangeLog:
* gdb.python/py-arch-reg-groups.exp: Additional tests.
Diffstat (limited to 'gdb/python')
-rw-r--r-- | gdb/python/py-registers.c | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c index 8e22a919..9396498 100644 --- a/gdb/python/py-registers.c +++ b/gdb/python/py-registers.c @@ -23,6 +23,7 @@ #include "disasm.h" #include "reggroups.h" #include "python-internal.h" +#include <unordered_map> /* Token to access per-gdbarch data related to register descriptors. */ static struct gdbarch_data *gdbpy_register_object_data = NULL; @@ -95,18 +96,36 @@ gdbpy_register_object_data_init (struct gdbarch *gdbarch) return (void *) vec; } -/* Create a new gdb.RegisterGroup object wrapping REGGROUP. */ +/* Return a gdb.RegisterGroup object wrapping REGGROUP. The register + group objects are cached, and the same Python object will always be + returned for the same REGGROUP pointer. */ -static PyObject * -gdbpy_new_reggroup (struct reggroup *reggroup) +static gdbpy_ref<> +gdbpy_get_reggroup (struct reggroup *reggroup) { - /* Create a new object and fill in its details. */ - reggroup_object *group - = PyObject_New (reggroup_object, ®group_object_type); - if (group == NULL) - return NULL; - group->reggroup = reggroup; - return (PyObject *) group; + /* Map from GDB's internal reggroup objects to the Python representation. + GDB's reggroups are global, and are never deleted, so using a map like + this is safe. */ + static std::unordered_map<struct reggroup *,gdbpy_ref<>> + gdbpy_reggroup_object_map; + + /* If there is not already a suitable Python object in the map then + create a new one, and add it to the map. */ + if (gdbpy_reggroup_object_map[reggroup] == nullptr) + { + /* Create a new object and fill in its details. */ + gdbpy_ref<reggroup_object> group + (PyObject_New (reggroup_object, ®group_object_type)); + if (group == NULL) + return NULL; + group->reggroup = reggroup; + gdbpy_reggroup_object_map[reggroup] + = gdbpy_ref<> ((PyObject *) group.release ()); + } + + /* Fetch the Python object wrapping REGGROUP from the map, increasing + the reference count is handled by the gdbpy_ref class. */ + return gdbpy_reggroup_object_map[reggroup]; } /* Convert a gdb.RegisterGroup to a string, it just returns the name of @@ -215,7 +234,7 @@ gdbpy_reggroup_iter_next (PyObject *self) } iter_obj->reggroup = next_group; - return gdbpy_new_reggroup (iter_obj->reggroup); + return gdbpy_get_reggroup (iter_obj->reggroup).release (); } /* Return a new gdb.RegisterGroupsIterator over all the register groups in |