[applying,to,mainline] dwarf-reader,corpus: Use interned string to lookup corpus interfaces by ID.
Commit Message
Hello,
This patch speeds up the lookup of a function or variable using the
function/variable ID. This patch is in preparation of many more
function lookup made during ABIXML emitting by patches coming up in
the future.
* include/abg-corpus.h (corpus::lookup_functions): Take an
interned_string instead of an std::string. Add an overload for
const char* string too, for debugging purposes.
* src/abg-corpus-priv.h (istr_fn_ptr_set_map_type)
(istr_var_ptr_map_type): Define new typedefs.
(corpus::exported_decls_builder::priv::{id_fns_map_,
id_var_map_}): Use the new istr_fn_ptr_set_map_type and
istr_var_ptr_map_type types for these data members.
(corpus::exported_decls_builder::priv::{id_fns_map, id_var_map,
add_fn_to_id_fns_map, var_id_is_in_id_var_map, add_var_to_map,
add_var_to_exported}): Adjust.
(corpus::priv::lookup_functions): Declare new member function.
* src/abg-corpus.cc
(corpus::exported_decls_builder::maybe_add_var_to_exported_vars): Adjust.
(corpus::priv::lookup_functions): Define new member function. The
code here comes from the code that was in
corpus::lookup_functions. This is a factorization of
corpus::lookup_functions.
(corpus::lookup_functions): Take an interned_string instead of the
previous. Factorize the code that was here into the new
corpus::priv::lookup_functions.
* src/abg-dwarf-reader.cc
(reader::symbol_already_belongs_to_a_function): Adjust the call to
corpus::lookup_functions to use an interned_string.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Applying to the master branch.
---
include/abg-corpus.h | 5 ++++-
src/abg-corpus-priv.h | 48 +++++++++++++++++++++++++++--------------
src/abg-corpus.cc | 48 ++++++++++++++++++++++++++++++++++-------
src/abg-dwarf-reader.cc | 2 +-
4 files changed, 77 insertions(+), 26 deletions(-)
@@ -219,7 +219,10 @@ public:
get_functions() const;
const std::unordered_set<function_decl*>*
- lookup_functions(const string& id) const;
+ lookup_functions(const interned_string& id) const;
+
+ const std::unordered_set<function_decl*>*
+ lookup_functions(const char* id) const;
void
sort_functions();
@@ -19,6 +19,7 @@
#include "abg-regex.h"
#include "abg-sptr-utils.h"
#include "abg-symtab-reader.h"
+#include "abg-interned-str.h"
namespace abigail
{
@@ -46,10 +47,22 @@ typedef unordered_map<string, vector<function_decl*> > str_fn_ptrs_map_type;
typedef unordered_map<string, std::unordered_set<function_decl*> >
str_fn_ptr_set_map_type;
+/// Convenience typedef for a hash map which key is an interned_string
+/// and which data is a set of abigail::ir::function_decl*
+typedef unordered_map<interned_string,
+ std::unordered_set<function_decl*>,
+ hash_interned_string> istr_fn_ptr_set_map_type;
+
/// Convenience typedef for a hash map which key is a string and
/// which data is an abigail::ir::var_decl*.
typedef unordered_map<string, var_decl*> str_var_ptr_map_type;
+/// Convenience typedef for a hash map which key is an interned_string
+/// and which data is an abigail::ir::var_decl*.
+typedef unordered_map<interned_string,
+ var_decl*,
+ hash_interned_string> istr_var_ptr_map_type;
+
/// The type of the private data of @ref
/// corpus::exported_decls_builder type.
class corpus::exported_decls_builder::priv
@@ -69,8 +82,8 @@ class corpus::exported_decls_builder::priv
// template parameters of the second instantiation are just typedefs
// of the first instantiation, for instance. So there can be cases
// where one ID appertains to more than one function.
- str_fn_ptr_set_map_type id_fns_map_;
- str_var_ptr_map_type id_var_map_;
+ istr_fn_ptr_set_map_type id_fns_map_;
+ istr_var_ptr_map_type id_var_map_;
strings_type& fns_suppress_regexps_;
regex_t_sptrs_type compiled_fns_suppress_regexp_;
strings_type& vars_suppress_regexps_;
@@ -203,7 +216,7 @@ public:
///
/// @return a map which key is a string and which data is a pointer
/// to a function.
- const str_fn_ptr_set_map_type&
+ const istr_fn_ptr_set_map_type&
id_fns_map() const
{return id_fns_map_;}
@@ -216,7 +229,7 @@ public:
///
/// @return a map which key is a string and which data is a pointer
/// to a function.
- str_fn_ptr_set_map_type&
+ istr_fn_ptr_set_map_type&
id_fns_map()
{return id_fns_map_;}
@@ -229,7 +242,7 @@ public:
///
/// @return a map which key is a string and which data is a pointer
/// to a function.
- const str_var_ptr_map_type&
+ const istr_var_ptr_map_type&
id_var_map() const
{return id_var_map_;}
@@ -242,7 +255,7 @@ public:
///
/// @return a map which key is a string and which data is a pointer
/// to a function.
- str_var_ptr_map_type&
+ istr_var_ptr_map_type&
id_var_map()
{return id_var_map_;}
@@ -274,10 +287,10 @@ public:
/// @return the pointer to the vector of functions with ID @p fn_id,
/// or nil if no function with that ID exists.
std::unordered_set<function_decl*>*
- fn_id_is_in_id_fns_map(const string& fn_id)
+ fn_id_is_in_id_fns_map(const interned_string& fn_id)
{
- str_fn_ptr_set_map_type& m = id_fns_map();
- str_fn_ptr_set_map_type::iterator i = m.find(fn_id);
+ istr_fn_ptr_set_map_type& m = id_fns_map();
+ auto i = m.find(fn_id);
if (i == m.end())
return 0;
return &i->second;
@@ -295,7 +308,7 @@ public:
std::unordered_set<function_decl*>*
fn_id_is_in_id_fns_map(const function_decl* fn)
{
- string fn_id = fn->get_id();
+ interned_string fn_id = fn->get_id();
return fn_id_is_in_id_fns_map(fn_id);
}
@@ -389,7 +402,7 @@ public:
return;
// First associate the function id to the function.
- string fn_id = fn->get_id();
+ interned_string fn_id = fn->get_id();
std::unordered_set<function_decl*>* fns = fn_id_is_in_id_fns_map(fn_id);
if (!fns)
fns = &(id_fns_map()[fn_id] = std::unordered_set<function_decl*>());
@@ -424,10 +437,10 @@ public:
/// @return true iff the variable designated by @p fn_id is present
/// in the set of exported variables.
bool
- var_id_is_in_id_var_map(const string& var_id) const
+ var_id_is_in_id_var_map(const interned_string& var_id) const
{
- const str_var_ptr_map_type& m = id_var_map();
- str_var_ptr_map_type::const_iterator i = m.find(var_id);
+ const istr_var_ptr_map_type& m = id_var_map();
+ auto i = m.find(var_id);
return i != m.end();
}
@@ -440,7 +453,7 @@ public:
{
if (var)
{
- const string& var_id = get_id(*var);
+ const interned_string& var_id = get_id(*var);
id_var_map()[var_id] = var;
}
}
@@ -464,7 +477,7 @@ public:
void
add_var_to_exported(const var_decl* var)
{
- const string& id = get_id(*var);
+ const interned_string& id = get_id(*var);
if (!var_id_is_in_id_var_map(id))
{
vars_.push_back(const_cast<var_decl*>(var));
@@ -813,6 +826,9 @@ public:
unordered_set<interned_string, hash_interned_string>*
get_public_types_pretty_representations();
+ std::unordered_set<function_decl*>*
+ lookup_functions(const interned_string& id);
+
~priv();
}; // end struct corpus::priv
@@ -184,7 +184,7 @@ corpus::exported_decls_builder::maybe_add_var_to_exported_vars(const var_decl* v
if (!var->get_is_in_public_symbol_table())
return;
- const string& var_id = priv_->get_id(*var);
+ const interned_string& var_id = priv_->get_id(*var);
ABG_ASSERT(!var_id.empty());
if (priv_->var_id_is_in_id_var_map(var_id))
@@ -630,6 +630,34 @@ corpus::priv::get_public_types_pretty_representations()
return pub_type_pretty_reprs_;
}
+/// Lookup the function which has a given function ID.
+///
+/// Note that there can have been several functions with the same ID.
+/// This is because debug info can declare the same function in
+/// several different translation units. Normally, all these function
+/// should be equal. But still, this function returns all these
+/// functions.
+///
+/// @param id the ID of the function to lookup. This ID must be
+/// either the result of invoking function::get_id() of
+/// elf_symbol::get_id_string().
+///
+/// @return the set of functions which ID is @p id, or nil if no
+/// function with that ID was found.
+std::unordered_set<function_decl*>*
+corpus::priv::lookup_functions(const interned_string& id)
+{
+ exported_decls_builder_sptr &b = exported_decls_builder;
+ if (b)
+ {
+ auto i = b->priv_->id_fns_map_.find(id);
+ if (i == b->priv_->id_fns_map_.end())
+ return 0;
+ return &i->second;
+ }
+ return nullptr;
+}
+
/// Destructor of the @ref corpus::priv type.
corpus::priv::~priv()
{
@@ -1335,16 +1363,20 @@ corpus::get_functions() const
/// either the result of invoking function::get_id() of
/// elf_symbol::get_id_string().
///
-/// @return the vector functions which ID is @p id, or nil if no
+/// @return the set of functions which ID is @p id, or nil if no
/// function with that ID was found.
const std::unordered_set<function_decl*>*
-corpus::lookup_functions(const string& id) const
+corpus::lookup_functions(const interned_string& id) const
+{return priv_->lookup_functions(id);}
+
+const std::unordered_set<function_decl*>*
+corpus::lookup_functions(const char* id) const
{
- exported_decls_builder_sptr b = get_exported_decls_builder();
- auto i = b->priv_->id_fns_map_.find(id);
- if (i == b->priv_->id_fns_map_.end())
- return 0;
- return &i->second;
+ if (!id)
+ return nullptr;
+
+ interned_string string_id = priv_->env.intern(id);
+ return lookup_functions(string_id);
}
/// Sort the set of functions exported by this corpus.
@@ -4486,7 +4486,7 @@ public:
if (!corp)
return false;
- string id = fn->get_id_string();
+ interned_string id = corp->get_environment().intern(fn->get_id_string());
const std::unordered_set<function_decl*> *fns = corp->lookup_functions(id);
if (!fns)