[applying,to,mainline] dwarf-reader,corpus: Use interned string to lookup corpus interfaces by ID.

Message ID 87il2txt9e.fsf@redhat.com
State New
Headers
Series [applying,to,mainline] dwarf-reader,corpus: Use interned string to lookup corpus interfaces by ID. |

Commit Message

Dodji Seketeli Feb. 12, 2024, 9:33 p.m. UTC
  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(-)
  

Patch

diff --git a/include/abg-corpus.h b/include/abg-corpus.h
index 6de251de..aafa3a1f 100644
--- a/include/abg-corpus.h
+++ b/include/abg-corpus.h
@@ -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();
diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index 412db377..6908142e 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -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
 
diff --git a/src/abg-corpus.cc b/src/abg-corpus.cc
index 4a4cb8bc..2a904079 100644
--- a/src/abg-corpus.cc
+++ b/src/abg-corpus.cc
@@ -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.
diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index dc491b93..36c8eea6 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -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)