[08/20] corpus: make get_unreferenced_(function|variable)_symbols use the new symtab

Message ID 20210127125853.886677-9-maennich@google.com
State Committed
Headers
Series Refactor (k)symtab reader |

Commit Message

Matthias Männich Jan. 27, 2021, 12:58 p.m. UTC
  Make the corresponding members an implementation detail of corpus::priv.
They get computed based on the new symtab whenever they are accessed
first with an atomic instantiation. That simplifies the implementation
and homogenizes the access to functions and variables. Sorting does not
need to be done as the symtab already gives a guarantee for that.

        * src/abg-corpus-priv.h (corpus::priv::unrefed_var_symbols): make
          private, mutable and optional.
          (corpus::unrefed_fun_symbols): Likewise.
          (corpus::priv::get_unreferenced_function_symbols): New method declaration.
          (corpus::priv::get_unreferenced_variable_symbols): Likewise.
        * src/abg-corpus.cc
          (corpus::priv::build_unreferenced_symbols_tables): Delete method.
          (corpus::priv::get_unreferenced_function_symbols): New method implementation.
          (corpus::priv::get_unreferenced_variable_symbols): Likewise.
          (corpus::get_unreferenced_function_symbols): Proxy call to corpus::priv.
          (corpus::get_unreferenced_variable_symbols): Likewise.

Reviewed-by: Giuliano Procida <gprocida@google.com>
Signed-off-by: Matthias Maennich <maennich@google.com>
---
 src/abg-corpus-priv.h |  13 ++-
 src/abg-corpus.cc     | 246 +++++++++++++++++++-----------------------
 2 files changed, 116 insertions(+), 143 deletions(-)
  

Comments

Dodji Seketeli March 15, 2021, 12:06 p.m. UTC | #1
Hello,

Matthias Maennich <maennich@google.com> a écrit:

[...]

> diff --git a/src/abg-corpus.cc b/src/abg-corpus.cc
> index 75f897eb72a8..f9f51a360707 100644
> --- a/src/abg-corpus.cc
> +++ b/src/abg-corpus.cc

[...]

> +/// Return a list of symbols that are not referenced by any function of
> +/// corpus::get_functions().
> +///
> +/// Note that this function considers the list of function symbols to keep,
> +/// that is provided by corpus::get_sym_ids_of_fns_to_keep(). If a given
> +/// unreferenced function symbol is not in the list of functions to keep, then
> +/// that symbol is dropped and will not be part of the resulting table of
> +/// unreferenced symbol that is built.

Please use the @return tag in this comment.

> +const elf_symbols&
> +corpus::priv::get_unreferenced_function_symbols() const
> +{

[...]

> +/// Return a list of symbols that are not referenced by any variable of
> +/// corpus::get_variables().
> +///
> +/// Note that this function considers the list of variable symbols to keep,
> +/// that is provided by corpus::get_sym_ids_of_vars_to_keep(). If a given
> +/// unreferenced variable symbol is not in the list of variable to keep, then
> +/// that symbol is dropped and will not be part of the resulting table of
> +/// unreferenced symbol that is built.

Likewise.

> +const elf_symbols&
> +corpus::priv::get_unreferenced_variable_symbols() const
> +{

[...]

>  /// Getter of the set of pretty representation of types that are
>  /// reachable from public interfaces (global functions and variables).
>  ///
> @@ -1310,12 +1290,7 @@ corpus::sort_variables()
>  /// function exported by the current corpus.
>  const elf_symbols&
>  corpus::get_unreferenced_function_symbols() const
> -{
> -  if (priv_->unrefed_fun_symbols.empty()
> -      && priv_->unrefed_var_symbols.empty())
> -    priv_->build_unreferenced_symbols_tables();
> -  return priv_->unrefed_fun_symbols;
> -}
> +{ return priv_->get_unreferenced_function_symbols(); }

Please remove leading/trailing spaces after/before the curly brackets.

>  
>  /// Getter of the set of variable symbols that are not referenced by
>  /// any variable exported by the current corpus.
> @@ -1328,12 +1303,7 @@ corpus::get_unreferenced_function_symbols() const
>  /// variable exported by the current corpus.
>  const elf_symbols&
>  corpus::get_unreferenced_variable_symbols() const
> -{
> -    if (priv_->unrefed_fun_symbols.empty()
> -      && priv_->unrefed_var_symbols.empty())
> -    priv_->build_unreferenced_symbols_tables();
> -  return priv_->unrefed_var_symbols;
> -}
> +{ return priv_->get_unreferenced_variable_symbols(); }

[...]

> Make the corresponding members an implementation detail of corpus::priv.
> They get computed based on the new symtab whenever they are accessed
> first with an atomic instantiation. That simplifies the implementation
> and homogenizes the access to functions and variables. Sorting does not
> need to be done as the symtab already gives a guarantee for that.
>
>         * src/abg-corpus-priv.h (corpus::priv::unrefed_var_symbols): make
>           private, mutable and optional.
>           (corpus::unrefed_fun_symbols): Likewise.
>           (corpus::priv::get_unreferenced_function_symbols): New method declaration.
>           (corpus::priv::get_unreferenced_variable_symbols): Likewise.
>         * src/abg-corpus.cc
>           (corpus::priv::build_unreferenced_symbols_tables): Delete method.
>           (corpus::priv::get_unreferenced_function_symbols): New method implementation.
>           (corpus::priv::get_unreferenced_variable_symbols): Likewise.
>           (corpus::get_unreferenced_function_symbols): Proxy call to corpus::priv.
>           (corpus::get_unreferenced_variable_symbols): Likewise.
>
> Reviewed-by: Giuliano Procida <gprocida@google.com>
> Signed-off-by: Matthias Maennich <maennich@google.com>

OK to apply to master with the above changes once the previous patches
have been applied.

Thanks!

[...]

cheers,
  

Patch

diff --git a/src/abg-corpus-priv.h b/src/abg-corpus-priv.h
index 282796e1b685..c8bf7f9d4cf6 100644
--- a/src/abg-corpus-priv.h
+++ b/src/abg-corpus-priv.h
@@ -686,8 +686,6 @@  struct corpus::priv
   symtab_reader::symtab_sptr			symtab_;
   string_elf_symbols_map_sptr			fun_symbol_map;
   string_elf_symbols_map_sptr			undefined_fun_symbol_map;
-  elf_symbols					unrefed_fun_symbols;
-  elf_symbols					unrefed_var_symbols;
   // The type maps contained in this data member are populated if the
   // corpus follows the One Definition Rule and thus if there is only
   // one copy of a type with a given name, per corpus. Otherwise, if
@@ -709,8 +707,10 @@  private:
 
   mutable abg_compat::optional<elf_symbols> sorted_var_symbols;
   mutable abg_compat::optional<elf_symbols> sorted_undefined_var_symbols;
+  mutable abg_compat::optional<elf_symbols> unrefed_var_symbols;
   mutable abg_compat::optional<elf_symbols> sorted_fun_symbols;
   mutable abg_compat::optional<elf_symbols> sorted_undefined_fun_symbols;
+  mutable abg_compat::optional<elf_symbols> unrefed_fun_symbols;
 
 public:
   priv(const string &	p,
@@ -722,9 +722,6 @@  public:
       pub_type_pretty_reprs_()
   {}
 
-  void
-  build_unreferenced_symbols_tables();
-
   type_maps&
   get_types();
 
@@ -737,12 +734,18 @@  public:
   const elf_symbols&
   get_sorted_undefined_fun_symbols() const;
 
+  const elf_symbols&
+  get_unreferenced_function_symbols() const;
+
   const elf_symbols&
   get_sorted_var_symbols() const;
 
   const elf_symbols&
   get_sorted_undefined_var_symbols() const;
 
+  const elf_symbols&
+  get_unreferenced_variable_symbols() const;
+
   unordered_set<interned_string, hash_interned_string>*
   get_public_types_pretty_representations();
 
diff --git a/src/abg-corpus.cc b/src/abg-corpus.cc
index 75f897eb72a8..f9f51a360707 100644
--- a/src/abg-corpus.cc
+++ b/src/abg-corpus.cc
@@ -302,132 +302,6 @@  struct comp_elf_symbols_functor
 
 // <corpus stuff>
 
-
-/// Build the tables of symbols that are not referenced by any
-/// function or variables of corpus::get_functions() or
-/// corpus::get_variables().
-///
-/// Note that this function considers the list of function and
-/// variable symbols to keep, that is provided by
-/// corpus::get_sym_ids_of_fns_to_keep() and
-/// corpus::get_sym_ids_of_vars_to_keep().  If a given unreferenced
-/// function or variable symbol is not in the list of variable and
-/// function symbols to keep, then that symbol is dropped and will not
-/// be part of the resulting table of unreferenced symbol that is
-/// built.
-///
-/// The built tables are accessible from
-/// corpus::get_unreferenced_function_symbols() and
-/// corpus::get_unreferenced_variable_symbols().
-void
-corpus::priv::build_unreferenced_symbols_tables()
-{
-  unordered_map<string, bool> refed_funs, refed_vars;
-  elf_symbol_sptr sym;
-
-  for (vector<function_decl*>::const_iterator f = fns.begin();
-       f != fns.end();
-       ++f)
-    if ((sym = (*f)->get_symbol()))
-      {
-	refed_funs[sym->get_id_string()] = true;
-	for (elf_symbol_sptr a = sym->get_next_alias();
-	     a && !a->is_main_symbol();
-	     a = a->get_next_alias())
-	  refed_funs[a->get_id_string()] = true;
-      }
-
-  for (vector<var_decl*>::const_iterator v = vars.begin();
-       v != vars.end();
-       ++v)
-    if ((sym = (*v)->get_symbol()))
-      {
-	refed_vars[sym->get_id_string()] = true;
-	for (elf_symbol_sptr a = sym->get_next_alias();
-	     a && !a->is_main_symbol();
-	     a = a->get_next_alias())
-	  refed_vars[a->get_id_string()] = true;
-      }
-
-  if (fun_symbol_map)
-    {
-      // Let's assume that the size of the unreferenced symbols vector
-      // is roughly smaller than the size of the symbol table.
-      unrefed_fun_symbols.reserve(fun_symbol_map->size());
-      for (string_elf_symbols_map_type::const_iterator i
-	     = fun_symbol_map->begin();
-	   i != fun_symbol_map->end();
-	   ++i)
-	for (elf_symbols::const_iterator s = i->second.begin();
-	     s != i->second.end();
-	     ++s)
-	  {
-	    string sym_id = (*s)->get_id_string();
-	    if (refed_funs.find(sym_id) == refed_funs.end())
-	      {
-		bool keep = sym_id_fns_to_keep.empty();
-		for (vector<string>::const_iterator i =
-		       sym_id_fns_to_keep.begin();
-		     i != sym_id_fns_to_keep.end();
-		     ++i)
-		  {
-		    if (*i == sym_id)
-		      {
-			keep = true;
-			break;
-		      }
-		  }
-		if (keep)
-		  unrefed_fun_symbols.push_back(*s);
-	      }
-	  }
-
-      comp_elf_symbols_functor comp;
-      std::sort(unrefed_fun_symbols.begin(),
-		unrefed_fun_symbols.end(),
-		comp);
-    }
-
-  if (var_symbol_map)
-    {
-      // Let's assume that the size of the unreferenced symbols vector
-      // is roughly smaller than the size of the symbol table.
-      unrefed_var_symbols.reserve(var_symbol_map->size());
-      for (string_elf_symbols_map_type::const_iterator i
-	     = var_symbol_map->begin();
-	   i != var_symbol_map->end();
-	   ++i)
-	for (elf_symbols::const_iterator s = i->second.begin();
-	     s != i->second.end();
-	     ++s)
-	  {
-	    string sym_id = (*s)->get_id_string();
-	    if (refed_vars.find(sym_id) == refed_vars.end())
-	      {
-		bool keep = sym_id_vars_to_keep.empty();
-		for (vector<string>::const_iterator i =
-		       sym_id_vars_to_keep.begin();
-		     i != sym_id_vars_to_keep.end();
-		     ++i)
-		  {
-		    if (*i == sym_id)
-		      {
-			keep = true;
-			break;
-		      }
-		  }
-		if (keep)
-		  unrefed_var_symbols.push_back(*s);
-	      }
-	  }
-
-      comp_elf_symbols_functor comp;
-      std::sort(unrefed_var_symbols.begin(),
-		unrefed_var_symbols.end(),
-		comp);
-    }
-}
-
 /// Get the maps that associate a name to a certain kind of type.
 type_maps&
 corpus::priv::get_types()
@@ -478,6 +352,59 @@  corpus::priv::get_sorted_undefined_fun_symbols() const
   return *sorted_undefined_fun_symbols;
 }
 
+/// Return a list of symbols that are not referenced by any function of
+/// corpus::get_functions().
+///
+/// Note that this function considers the list of function symbols to keep,
+/// that is provided by corpus::get_sym_ids_of_fns_to_keep(). If a given
+/// unreferenced function symbol is not in the list of functions to keep, then
+/// that symbol is dropped and will not be part of the resulting table of
+/// unreferenced symbol that is built.
+const elf_symbols&
+corpus::priv::get_unreferenced_function_symbols() const
+{
+  if (!unrefed_fun_symbols)
+    {
+      unrefed_fun_symbols = elf_symbols();
+      if (symtab_)
+	{
+	  unordered_map<string, bool> refed_funs;
+
+	  for (const auto& function : fns)
+	    if (elf_symbol_sptr sym = function->get_symbol())
+	      {
+		refed_funs[sym->get_id_string()] = true;
+		for (elf_symbol_sptr a = sym->get_next_alias();
+		     a && !a->is_main_symbol(); a = a->get_next_alias())
+		  refed_funs[a->get_id_string()] = true;
+	      }
+
+	  auto filter = symtab_->make_filter();
+	  filter.set_functions();
+	  for (const auto& symbol :
+	       symtab_reader::filtered_symtab(*symtab_, filter))
+	    {
+	      const std::string sym_id = symbol->get_id_string();
+	      if (refed_funs.find(sym_id) == refed_funs.end())
+		{
+		  bool keep = sym_id_fns_to_keep.empty();
+		  for (const auto& id : sym_id_fns_to_keep)
+		    {
+		      if (id == sym_id)
+			{
+			  keep = true;
+			  break;
+			}
+		    }
+		  if (keep)
+		    unrefed_fun_symbols->push_back(symbol);
+		}
+	    }
+	}
+    }
+  return *unrefed_fun_symbols;
+}
+
 /// Getter for the sorted vector of variable symbols for this corpus.
 ///
 /// Note that the first time this function is called, it computes the
@@ -519,6 +446,59 @@  corpus::priv::get_sorted_undefined_var_symbols() const
   return *sorted_undefined_var_symbols;
 }
 
+/// Return a list of symbols that are not referenced by any variable of
+/// corpus::get_variables().
+///
+/// Note that this function considers the list of variable symbols to keep,
+/// that is provided by corpus::get_sym_ids_of_vars_to_keep(). If a given
+/// unreferenced variable symbol is not in the list of variable to keep, then
+/// that symbol is dropped and will not be part of the resulting table of
+/// unreferenced symbol that is built.
+const elf_symbols&
+corpus::priv::get_unreferenced_variable_symbols() const
+{
+  if (!unrefed_var_symbols)
+    {
+      unrefed_var_symbols = elf_symbols();
+      if (symtab_)
+	{
+	  unordered_map<string, bool> refed_vars;
+	  for (const auto& variable : vars)
+	    if (elf_symbol_sptr sym = variable->get_symbol())
+	      {
+		refed_vars[sym->get_id_string()] = true;
+		for (elf_symbol_sptr a = sym->get_next_alias();
+		     a && !a->is_main_symbol(); a = a->get_next_alias())
+		  refed_vars[a->get_id_string()] = true;
+	      }
+
+	  auto filter = symtab_->make_filter();
+	  filter.set_variables();
+	  for (const auto& symbol :
+	       symtab_reader::filtered_symtab(*symtab_, filter))
+	    {
+	      const std::string sym_id = symbol->get_id_string();
+	      if (refed_vars.find(sym_id) == refed_vars.end())
+		{
+		  bool keep = sym_id_vars_to_keep.empty();
+		  for (const auto& id : sym_id_vars_to_keep)
+		    {
+		      if (id == sym_id)
+			{
+			  keep = true;
+			  break;
+			}
+		    }
+		  if (keep)
+		    unrefed_var_symbols->push_back(symbol);
+		}
+	    }
+	}
+    }
+  return *unrefed_var_symbols;
+}
+
+
 /// Getter of the set of pretty representation of types that are
 /// reachable from public interfaces (global functions and variables).
 ///
@@ -1310,12 +1290,7 @@  corpus::sort_variables()
 /// function exported by the current corpus.
 const elf_symbols&
 corpus::get_unreferenced_function_symbols() const
-{
-  if (priv_->unrefed_fun_symbols.empty()
-      && priv_->unrefed_var_symbols.empty())
-    priv_->build_unreferenced_symbols_tables();
-  return priv_->unrefed_fun_symbols;
-}
+{ return priv_->get_unreferenced_function_symbols(); }
 
 /// Getter of the set of variable symbols that are not referenced by
 /// any variable exported by the current corpus.
@@ -1328,12 +1303,7 @@  corpus::get_unreferenced_function_symbols() const
 /// variable exported by the current corpus.
 const elf_symbols&
 corpus::get_unreferenced_variable_symbols() const
-{
-    if (priv_->unrefed_fun_symbols.empty()
-      && priv_->unrefed_var_symbols.empty())
-    priv_->build_unreferenced_symbols_tables();
-  return priv_->unrefed_var_symbols;
-}
+{ return priv_->get_unreferenced_variable_symbols(); }
 
 /// Accessor for the regex patterns describing the functions to drop
 /// from the public decl table.