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 | |
parent | f7306dac19c502232f766c3881313857915f330d (diff) | |
download | gdb-baf8791efb4b5cb41348b11ad9f63e6c2a004c5f.zip gdb-baf8791efb4b5cb41348b11ad9f63e6c2a004c5f.tar.gz 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.
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/python/py-registers.c | 41 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-arch-reg-groups.exp | 19 |
4 files changed, 61 insertions, 11 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e2d2e15..31307e6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,13 @@ 2020-07-21 Andrew Burgess <andrew.burgess@embecosm.com> + * 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. + +2020-07-21 Andrew Burgess <andrew.burgess@embecosm.com> + * python/py-registers.c (gdbpy_register_object_data): New static global. (gdbpy_register_object_data_init): New function. 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 diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 6b13e92..1f0861e 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2020-07-21 Andrew Burgess <andrew.burgess@embecosm.com> + * gdb.python/py-arch-reg-groups.exp: Additional tests. + +2020-07-21 Andrew Burgess <andrew.burgess@embecosm.com> + * gdb.python/py-arch-reg-names.exp: Additional tests. 2020-07-21 Tom de Vries <tdevries@suse.de> diff --git a/gdb/testsuite/gdb.python/py-arch-reg-groups.exp b/gdb/testsuite/gdb.python/py-arch-reg-groups.exp index ea9aa77..093de2e 100644 --- a/gdb/testsuite/gdb.python/py-arch-reg-groups.exp +++ b/gdb/testsuite/gdb.python/py-arch-reg-groups.exp @@ -85,3 +85,22 @@ for { set i 0 } { $i < [llength $groups] } { incr i } { } } gdb_assert { $found_non_match == 0 } "all register groups match" + +# Check that we get the same register group descriptors from two +# different iterators. +gdb_py_test_silent_cmd \ + "python iter1 = arch.register_groups ()" \ + "get first all register group iterator" 0 +gdb_py_test_silent_cmd \ + "python iter2 = arch.register_groups ()" \ + "get second all register group 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 |