mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-26 17:18:55 +00:00
Two-level map
Change-Id: I008ddd9a1ef773a8d17e439d24d75d37bbf1a076
This commit is contained in:
committed by
Simon Marchi
parent
5672720dd1
commit
fe0e47ac81
146
gdb/regcache.c
146
gdb/regcache.c
@@ -313,41 +313,17 @@ reg_buffer::assert_regnum (int regnum) const
|
||||
gdb_assert (regnum < gdbarch_num_regs (arch ()));
|
||||
}
|
||||
|
||||
/* Key type for target_ptid_regcache_map. */
|
||||
/* Type to map a ptid to a list of regcaches (one thread may have multiple
|
||||
regcaches, associated to different gdbarches). */
|
||||
|
||||
struct target_ptid
|
||||
{
|
||||
target_ptid (process_stratum_target *target, ptid_t ptid)
|
||||
: target (target), ptid (ptid)
|
||||
{}
|
||||
using ptid_regcache_map
|
||||
= std::unordered_multimap<ptid_t, regcache_up, hash_ptid>;
|
||||
|
||||
process_stratum_target *target;
|
||||
ptid_t ptid;
|
||||
|
||||
bool operator== (const target_ptid &other) const
|
||||
{
|
||||
return (this->target == other.target
|
||||
&& this->ptid == other.ptid);
|
||||
}
|
||||
};
|
||||
|
||||
/* Hash function for target_ptid. */
|
||||
|
||||
struct hash_target_ptid
|
||||
{
|
||||
size_t operator() (const target_ptid &val) const
|
||||
{
|
||||
std::hash<process_stratum_target *> h_ptr;
|
||||
hash_ptid h_ptid;
|
||||
|
||||
return h_ptr (val.target) + h_ptid (val.ptid);
|
||||
}
|
||||
};
|
||||
|
||||
/* Type to map a (target, ptid) tuple to a regcache. */
|
||||
/* Type to map a target to a ptid_regcache_map, holding the regcaches for the
|
||||
threads defined by that target. */
|
||||
|
||||
using target_ptid_regcache_map
|
||||
= std::unordered_multimap<target_ptid, regcache_up, hash_target_ptid>;
|
||||
= std::unordered_map<process_stratum_target *, ptid_regcache_map>;
|
||||
|
||||
/* Global structure containing the existing regcaches. */
|
||||
|
||||
@@ -364,9 +340,11 @@ get_thread_arch_aspace_regcache (process_stratum_target *target,
|
||||
{
|
||||
gdb_assert (target != nullptr);
|
||||
|
||||
/* Look up the regcache for this (target, ptid, arch). */
|
||||
target_ptid key (target, ptid);
|
||||
auto range = regcaches.equal_range (key);
|
||||
/* Find the ptid -> regcache map for this target. */
|
||||
auto &ptid_regc_map = regcaches[target];
|
||||
|
||||
/* Check first if a regcache for this arch already exists. */
|
||||
auto range = ptid_regc_map.equal_range (ptid);
|
||||
for (auto it = range.first; it != range.second; it++)
|
||||
{
|
||||
if (it->second->arch () == arch)
|
||||
@@ -374,11 +352,9 @@ get_thread_arch_aspace_regcache (process_stratum_target *target,
|
||||
}
|
||||
|
||||
/* It does not exist, create it. */
|
||||
regcache *new_regcache = new regcache (target, arch, aspace);
|
||||
regcache *new_regcache (new regcache (target, arch, aspace));
|
||||
new_regcache->set_ptid (ptid);
|
||||
|
||||
/* Insert it in the map. */
|
||||
regcaches.insert (std::make_pair (key, new_regcache));
|
||||
ptid_regc_map.insert (std::make_pair (ptid, new_regcache));
|
||||
|
||||
return new_regcache;
|
||||
}
|
||||
@@ -458,19 +434,22 @@ static void
|
||||
regcache_thread_ptid_changed (process_stratum_target *target,
|
||||
ptid_t old_ptid, ptid_t new_ptid)
|
||||
{
|
||||
target_ptid old_key (target, old_ptid);
|
||||
target_ptid new_key (target, new_ptid);
|
||||
auto ptid_regc_map_it = regcaches.find (target);
|
||||
|
||||
auto range = regcaches.equal_range (old_key);
|
||||
if (ptid_regc_map_it == regcaches.end ())
|
||||
return;
|
||||
|
||||
auto &ptid_regc_map = ptid_regc_map_it->second;
|
||||
auto range = ptid_regc_map.equal_range (old_ptid);
|
||||
for (auto it = range.first; it != range.second;)
|
||||
{
|
||||
regcache_up rc = std::move (it->second);
|
||||
rc->set_ptid (new_ptid);
|
||||
|
||||
/* Remove old before inserting new, to avoid rehashing, which would
|
||||
invalidate iterators. */
|
||||
it = regcaches.erase (it);
|
||||
regcaches.insert (std::make_pair (new_key, std::move (rc)));
|
||||
/* Remove old before inserting new, to avoid rehashing,
|
||||
which would invalidate iterators. */
|
||||
it = ptid_regc_map.erase (it);
|
||||
ptid_regc_map.insert (std::make_pair (new_ptid, std::move (rc)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,29 +474,31 @@ registers_changed_ptid (process_stratum_target *target, ptid_t ptid)
|
||||
gdb_assert (ptid == minus_one_ptid);
|
||||
|
||||
/* Delete all the regcaches. */
|
||||
regcaches.clear ();
|
||||
for (auto &pair : regcaches)
|
||||
pair.second.clear ();
|
||||
}
|
||||
else if (ptid != minus_one_ptid)
|
||||
{
|
||||
/* Non-NULL target and non-minus_one_ptid, delete all regcaches belonging
|
||||
to this (TARGET, PTID). */
|
||||
regcaches.erase (target_ptid (target, ptid));
|
||||
to this (TARGET, PTID). */
|
||||
auto ptid_regc_map_it = regcaches.find (target);
|
||||
if (ptid_regc_map_it != regcaches.end ())
|
||||
{
|
||||
auto &ptid_regc_map = ptid_regc_map_it->second;
|
||||
ptid_regc_map.erase (ptid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non-NULL target and minus_one_ptid, delete all regcaches associated
|
||||
to this target.
|
||||
|
||||
We unfortunately don't have an efficient way to do this. Fall back
|
||||
to iterating all items to find all those belonging to TARGET. */
|
||||
for (auto it = regcaches.begin (); it != regcaches.end ();)
|
||||
{
|
||||
if (it->second->target () == target)
|
||||
it = regcaches.erase (it);
|
||||
else
|
||||
it++;
|
||||
}
|
||||
}
|
||||
/* Non-NULL target and minus_one_ptid, delete all regcaches
|
||||
associated to this target. */
|
||||
auto ptid_regc_map_it = regcaches.find (target);
|
||||
if (ptid_regc_map_it != regcaches.end ())
|
||||
{
|
||||
auto &ptid_regc_map = ptid_regc_map_it->second;
|
||||
ptid_regc_map.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
if ((target == nullptr || current_thread_target == target)
|
||||
&& current_thread_ptid.matches (ptid))
|
||||
@@ -1498,6 +1479,18 @@ register_dump::dump (ui_file *file)
|
||||
|
||||
namespace selftests {
|
||||
|
||||
static size_t
|
||||
regcaches_size ()
|
||||
{
|
||||
size_t size = 0;
|
||||
for (auto it = regcaches.begin (); it != regcaches.end (); ++it)
|
||||
{
|
||||
auto &ptid_regc_map = it->second;
|
||||
size += ptid_regc_map.size ();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Wrapper around get_thread_arch_aspace_regcache that does some self checks. */
|
||||
|
||||
static void
|
||||
@@ -1517,7 +1510,7 @@ static void
|
||||
regcaches_test (void)
|
||||
{
|
||||
/* It is empty at the start. */
|
||||
SELF_CHECK (regcaches.size () == 0);
|
||||
SELF_CHECK (regcaches_size () == 0);
|
||||
|
||||
ptid_t ptid1 (1), ptid2 (2), ptid3 (3);
|
||||
|
||||
@@ -1529,52 +1522,52 @@ regcaches_test (void)
|
||||
test_get_thread_arch_aspace_regcache (&test_target1, ptid1,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcaches.size () == 1);
|
||||
SELF_CHECK (regcaches_size () == 1);
|
||||
|
||||
/* Get regcache from (target1,ptid2), a new regcache is added to
|
||||
REGCACHES. */
|
||||
test_get_thread_arch_aspace_regcache (&test_target1, ptid2,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcaches.size () == 2);
|
||||
SELF_CHECK (regcaches_size () == 2);
|
||||
|
||||
/* Get regcache from (target1,ptid3), a new regcache is added to
|
||||
REGCACHES. */
|
||||
test_get_thread_arch_aspace_regcache (&test_target1, ptid3,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcaches.size () == 3);
|
||||
SELF_CHECK (regcaches_size () == 3);
|
||||
|
||||
/* Get regcache from (target1,ptid2) again, nothing is added to
|
||||
REGCACHES. */
|
||||
test_get_thread_arch_aspace_regcache (&test_target1, ptid2,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcaches.size () == 3);
|
||||
SELF_CHECK (regcaches_size () == 3);
|
||||
|
||||
/* Get regcache from (target2,ptid2), a new regcache is added to
|
||||
REGCACHES, since this time we're using a different target. */
|
||||
test_get_thread_arch_aspace_regcache (&test_target2, ptid2,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcaches.size () == 4);
|
||||
SELF_CHECK (regcaches_size () == 4);
|
||||
|
||||
/* Mark that (target1,ptid2) changed. The regcache of (target1,
|
||||
ptid2) should be removed from REGCACHES. */
|
||||
registers_changed_ptid (&test_target1, ptid2);
|
||||
SELF_CHECK (regcaches.size () == 3);
|
||||
SELF_CHECK (regcaches_size () == 3);
|
||||
|
||||
/* Get the regcache from (target2,ptid2) again, confirming the
|
||||
registers_changed_ptid call above did not delete it. */
|
||||
test_get_thread_arch_aspace_regcache (&test_target2, ptid2,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcaches.size () == 3);
|
||||
SELF_CHECK (regcaches_size () == 3);
|
||||
|
||||
/* Confirm that marking all regcaches of all targets as changed
|
||||
clears REGCACHES. */
|
||||
registers_changed_ptid (nullptr, minus_one_ptid);
|
||||
SELF_CHECK (regcaches.size () == 0);
|
||||
SELF_CHECK (regcaches_size () == 0);
|
||||
}
|
||||
|
||||
class target_ops_no_register : public test_target_ops
|
||||
@@ -1911,11 +1904,16 @@ regcache_thread_ptid_changed ()
|
||||
|
||||
/* Return the count of regcaches for (TARGET, PTID) in REGCACHES. */
|
||||
auto regcache_count = [] (process_stratum_target *target, ptid_t ptid)
|
||||
-> int
|
||||
{
|
||||
target_ptid key (target, ptid);
|
||||
|
||||
auto range = regcaches.equal_range (key);
|
||||
return std::distance (range.first, range.second);
|
||||
auto ptid_regc_map_it = regcaches.find (target);
|
||||
if (ptid_regc_map_it != regcaches.end ())
|
||||
{
|
||||
auto &ptid_regc_map = ptid_regc_map_it->second;
|
||||
auto range = ptid_regc_map.equal_range (ptid);
|
||||
return std::distance (range.first, range.second);
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
gdb_assert (regcaches.size () == 2);
|
||||
|
||||
Reference in New Issue
Block a user