* [PATCH 0/2] Avoid copying in name lookup
@ 2020-03-20 20:49 Tom Tromey
2020-03-20 20:49 ` [PATCH 1/2] Avoid some copying in psymtab.c Tom Tromey
2020-03-20 20:49 ` [PATCH 2/2] Avoid copying in lookup_name_info Tom Tromey
0 siblings, 2 replies; 13+ messages in thread
From: Tom Tromey @ 2020-03-20 20:49 UTC (permalink / raw)
To: gdb-patches
I noticed that some name lookup code was copying string when it was
not strictly necessary.
This series fixes the two problems I found.
Regression tested on x86-64 Fedora 30.
Let me know what you think.
Tom
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/2] Avoid some copying in psymtab.c
2020-03-20 20:49 [PATCH 0/2] Avoid copying in name lookup Tom Tromey
@ 2020-03-20 20:49 ` Tom Tromey
2020-03-31 17:46 ` Pedro Alves
2020-03-20 20:49 ` [PATCH 2/2] Avoid copying in lookup_name_info Tom Tromey
1 sibling, 1 reply; 13+ messages in thread
From: Tom Tromey @ 2020-03-20 20:49 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
I noticed that psymtab.c was always copying the search string in
psymtab_search_name, even when it wasn't necessary. This patch
replaces this function with a class which holds the allocated search
name, if necessary.
Once I had done that, I noticed that lookup_partial_symbol was
creating a lookup_name_info. However, this function called in loops,
causing even more excess allocation. This patch further fixes this by
hosting the creation of the lookup_name_info into the callers.
gdb/ChangeLog
2020-03-20 Tom Tromey <tromey@adacore.com>
* psymtab.c (class psymtab_search_name): New class.
(psymtab_search_name): Remove function.
(psym_lookup_symbol): Create search name and lookup name here.
(lookup_partial_symbol): Remove "name" parameter; add
lookup_name.
(psym_expand_symtabs_for_function): Update.
---
gdb/ChangeLog | 9 +++++
gdb/psymtab.c | 94 ++++++++++++++++++++++++++++-----------------------
2 files changed, 61 insertions(+), 42 deletions(-)
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index f77f6d5108f..34b9741e966 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -39,7 +39,8 @@
static struct partial_symbol *lookup_partial_symbol (struct objfile *,
struct partial_symtab *,
- const char *, int,
+ const lookup_name_info &,
+ int,
domain_enum);
static const char *psymtab_to_fullname (struct partial_symtab *ps);
@@ -469,6 +470,38 @@ find_pc_sect_psymbol (struct objfile *objfile,
return best;
}
+/* Returns the name used to search psymtabs. Unlike symtabs, psymtabs do
+ not contain any method/function instance information (since this would
+ force reading type information while reading psymtabs). Therefore,
+ if NAME contains overload information, it must be stripped before searching
+ psymtabs. */
+
+class psymtab_search_name
+{
+public:
+ explicit psymtab_search_name (const char *name)
+ : m_name (name)
+ {
+ if (current_language->la_language == language_cplus && strchr (name, '('))
+ m_search_name = cp_remove_params (name);
+ }
+
+ /* Return the search name. */
+ const char *get () const
+ {
+ if (m_search_name == nullptr)
+ return m_name;
+ return m_search_name.get ();
+ }
+
+private:
+
+ /* The original name. */
+ const char *m_name;
+ /* The search name, if one was needed. */
+ gdb::unique_xmalloc_ptr<char> m_search_name;
+};
+
/* Psymtab version of lookup_symbol. See its definition in
the definition of quick_symbol_functions in symfile.h. */
@@ -482,9 +515,14 @@ psym_lookup_symbol (struct objfile *objfile,
lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
+ psymtab_search_name search_name (name);
+ lookup_name_info psym_lookup_name (search_name.get (),
+ symbol_name_match_type::FULL);
+
for (partial_symtab *ps : require_partial_symbols (objfile, true))
{
- if (!ps->readin_p () && lookup_partial_symbol (objfile, ps, name,
+ if (!ps->readin_p () && lookup_partial_symbol (objfile, ps,
+ psym_lookup_name,
psymtab_index, domain))
{
struct symbol *sym, *with_opaque = NULL;
@@ -612,42 +650,14 @@ match_partial_symbol (struct objfile *objfile,
return NULL;
}
-/* Returns the name used to search psymtabs. Unlike symtabs, psymtabs do
- not contain any method/function instance information (since this would
- force reading type information while reading psymtabs). Therefore,
- if NAME contains overload information, it must be stripped before searching
- psymtabs. */
-
-static gdb::unique_xmalloc_ptr<char>
-psymtab_search_name (const char *name)
-{
- switch (current_language->la_language)
- {
- case language_cplus:
- {
- if (strchr (name, '('))
- {
- gdb::unique_xmalloc_ptr<char> ret = cp_remove_params (name);
-
- if (ret)
- return ret;
- }
- }
- break;
-
- default:
- break;
- }
-
- return make_unique_xstrdup (name);
-}
-
-/* Look, in partial_symtab PST, for symbol whose natural name is NAME.
- Check the global symbols if GLOBAL, the static symbols if not. */
+/* Look, in partial_symtab PST, for symbol whose natural name is
+ LOOKUP_NAME. Check the global symbols if GLOBAL, the static
+ symbols if not. */
static struct partial_symbol *
lookup_partial_symbol (struct objfile *objfile,
- struct partial_symtab *pst, const char *name,
+ struct partial_symtab *pst,
+ const lookup_name_info &lookup_name,
int global, domain_enum domain)
{
struct partial_symbol **start, **psym;
@@ -658,10 +668,6 @@ lookup_partial_symbol (struct objfile *objfile,
if (length == 0)
return NULL;
- gdb::unique_xmalloc_ptr<char> search_name = psymtab_search_name (name);
-
- lookup_name_info lookup_name (search_name.get (), symbol_name_match_type::FULL);
-
start = (global ?
&objfile->partial_symtabs->global_psymbols[pst->globals_offset] :
&objfile->partial_symtabs->static_psymbols[pst->statics_offset]);
@@ -686,7 +692,7 @@ lookup_partial_symbol (struct objfile *objfile,
internal_error (__FILE__, __LINE__,
_("failed internal consistency check"));
if (strcmp_iw_ordered ((*center)->ginfo.search_name (),
- search_name.get ()) >= 0)
+ lookup_name.name ().c_str ()) >= 0)
{
top = center;
}
@@ -1044,14 +1050,18 @@ static void
psym_expand_symtabs_for_function (struct objfile *objfile,
const char *func_name)
{
+ psymtab_search_name search_name (func_name);
+ lookup_name_info lookup_name (search_name.get (),
+ symbol_name_match_type::FULL);
+
for (partial_symtab *ps : require_partial_symbols (objfile, true))
{
if (ps->readin_p ())
continue;
- if ((lookup_partial_symbol (objfile, ps, func_name, 1, VAR_DOMAIN)
+ if ((lookup_partial_symbol (objfile, ps, lookup_name, 1, VAR_DOMAIN)
!= NULL)
- || (lookup_partial_symbol (objfile, ps, func_name, 0, VAR_DOMAIN)
+ || (lookup_partial_symbol (objfile, ps, lookup_name, 0, VAR_DOMAIN)
!= NULL))
psymtab_to_symtab (objfile, ps);
}
--
2.21.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/2] Avoid copying in lookup_name_info
2020-03-20 20:49 [PATCH 0/2] Avoid copying in name lookup Tom Tromey
2020-03-20 20:49 ` [PATCH 1/2] Avoid some copying in psymtab.c Tom Tromey
@ 2020-03-20 20:49 ` Tom Tromey
2020-03-23 17:51 ` Christian Biesinger
2020-03-31 18:18 ` Pedro Alves
1 sibling, 2 replies; 13+ messages in thread
From: Tom Tromey @ 2020-03-20 20:49 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
lookup_name_info always copies the name that is passed in. However,
normally a copy is not needed. This patch changes this class to avoid
copying. This required changing the "name" method to return something
else; I chose a gdb::string_view, to avoid excessive calls to strlen
in the code using the lookup_name_info. However, as this class does
not allow an arbitrary string_view, I've also added a c_str method
that guarantees a \0-terminated result -- a pedantic difference but
one that respects the string_view contract, IMO.
gdb/ChangeLog
2020-03-20 Tom Tromey <tromey@adacore.com>
* symtab.h (class lookup_name_info) <lookup_name_info>: Change
"name" parameter to rvalue reference. Initialize m_name_holder.
<lookup_name_info>: New overloads.
<name>: Return gdb::string_view.
<c_str>: New method.
<make_ignore_params>: Update.
<search_name_hash>: Update.
<language_lookup_name>: Return const char *.
<m_name_holder>: Rename from m_name.
<m_name>: New member.
* symtab.c (demangle_for_lookup_info::demangle_for_lookup_info)
(demangle_for_lookup_info::demangle_for_lookup_info): Update.
(lookup_name_info::match_any): Update.
* psymtab.c (match_partial_symbol, lookup_partial_symbol):
Update.
* minsyms.c (linkage_name_str): Update.
* language.c (default_symbol_name_matcher): Update.
* dwarf2/read.c (mapped_index_base::find_name_components_bounds):
Update.
* ada-lang.c (ada_fold_name): Change parameter to string_view.
(ada_lookup_name_info::ada_lookup_name_info): Update.
(literal_symbol_name_matcher): Update.
---
gdb/ChangeLog | 25 ++++++++++++++++++++
gdb/ada-lang.c | 29 ++++++++++++-----------
gdb/dwarf2/read.c | 2 +-
gdb/language.c | 4 ++--
gdb/minsyms.c | 2 +-
gdb/psymtab.c | 5 ++--
gdb/symtab.c | 8 +++----
gdb/symtab.h | 59 +++++++++++++++++++++++++++++++++++++----------
8 files changed, 98 insertions(+), 36 deletions(-)
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 2822d40c8cd..c38ed1fca0e 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -1016,17 +1016,17 @@ ada_encode (const char *decoded)
to next call. */
static char *
-ada_fold_name (const char *name)
+ada_fold_name (gdb::string_view name)
{
static char *fold_buffer = NULL;
static size_t fold_buffer_size = 0;
- int len = strlen (name);
+ int len = name.size ();
GROW_VECT (fold_buffer, fold_buffer_size, len + 1);
if (name[0] == '\'')
{
- strncpy (fold_buffer, name + 1, len - 2);
+ strncpy (fold_buffer, name.data () + 1, len - 2);
fold_buffer[len - 2] = '\000';
}
else
@@ -13953,14 +13953,16 @@ do_exact_match (const char *symbol_search_name,
ada_lookup_name_info::ada_lookup_name_info (const lookup_name_info &lookup_name)
{
- const std::string &user_name = lookup_name.name ();
+ gdb::string_view user_name = lookup_name.name ();
if (user_name[0] == '<')
{
if (user_name.back () == '>')
- m_encoded_name = user_name.substr (1, user_name.size () - 2);
+ m_encoded_name
+ = user_name.substr (1, user_name.size () - 2).to_string ();
else
- m_encoded_name = user_name.substr (1, user_name.size () - 1);
+ m_encoded_name
+ = user_name.substr (1, user_name.size () - 1).to_string ();
m_encoded_p = true;
m_verbatim_p = true;
m_wild_match_p = false;
@@ -13970,19 +13972,19 @@ ada_lookup_name_info::ada_lookup_name_info (const lookup_name_info &lookup_name)
{
m_verbatim_p = false;
- m_encoded_p = user_name.find ("__") != std::string::npos;
+ m_encoded_p = user_name.find ("__") != gdb::string_view::npos;
if (!m_encoded_p)
{
- const char *folded = ada_fold_name (user_name.c_str ());
+ const char *folded = ada_fold_name (user_name);
const char *encoded = ada_encode_1 (folded, false);
if (encoded != NULL)
m_encoded_name = encoded;
else
- m_encoded_name = user_name;
+ m_encoded_name = user_name.to_string ();
}
else
- m_encoded_name = user_name;
+ m_encoded_name = user_name.to_string ();
/* Handle the 'package Standard' special case. See description
of m_standard_p. */
@@ -14029,11 +14031,12 @@ literal_symbol_name_matcher (const char *symbol_search_name,
const lookup_name_info &lookup_name,
completion_match_result *comp_match_res)
{
- const std::string &name = lookup_name.name ();
+ gdb::string_view name_view = lookup_name.name ();
+ const char *name = lookup_name.c_str ();
int cmp = (lookup_name.completion_mode ()
- ? strncmp (symbol_search_name, name.c_str (), name.size ())
- : strcmp (symbol_search_name, name.c_str ()));
+ ? strncmp (symbol_search_name, name, name_view.size ())
+ : strcmp (symbol_search_name, name));
if (cmp == 0)
{
if (comp_match_res != NULL)
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 0e879e08a0c..cdccd04c54a 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -3774,7 +3774,7 @@ mapped_index_base::find_name_components_bounds
= this->name_components_casing == case_sensitive_on ? strcmp : strcasecmp;
const char *lang_name
- = lookup_name_without_params.language_lookup_name (lang).c_str ();
+ = lookup_name_without_params.language_lookup_name (lang);
/* Comparison function object for lower_bound that matches against a
given symbol name. */
diff --git a/gdb/language.c b/gdb/language.c
index 454c6dc45a7..c13fd1a406a 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -699,14 +699,14 @@ default_symbol_name_matcher (const char *symbol_search_name,
const lookup_name_info &lookup_name,
completion_match_result *comp_match_res)
{
- const std::string &name = lookup_name.name ();
+ gdb::string_view name = lookup_name.name ();
completion_match_for_lcd *match_for_lcd
= (comp_match_res != NULL ? &comp_match_res->match_for_lcd : NULL);
strncmp_iw_mode mode = (lookup_name.completion_mode ()
? strncmp_iw_mode::NORMAL
: strncmp_iw_mode::MATCH_PARAMS);
- if (strncmp_iw_with_mode (symbol_search_name, name.c_str (), name.size (),
+ if (strncmp_iw_with_mode (symbol_search_name, name.data (), name.size (),
mode, language_minimal, match_for_lcd) == 0)
{
if (comp_match_res != NULL)
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index e238355dc11..d2ac8172eea 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -467,7 +467,7 @@ linkage_name_str (const lookup_name_info &lookup_name)
if (current_language->la_language == language_ada)
return lookup_name.ada ().lookup_name ().c_str ();
- return lookup_name.name ().c_str ();
+ return lookup_name.c_str ();
}
/* See minsyms.h. */
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index 34b9741e966..7ab861632eb 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -612,8 +612,7 @@ match_partial_symbol (struct objfile *objfile,
gdb_assert (center < top);
enum language lang = (*center)->ginfo.language ();
- const char *lang_ln
- = name.language_lookup_name (lang).c_str ();
+ const char *lang_ln = name.language_lookup_name (lang);
if (ordered_compare ((*center)->ginfo.search_name (),
lang_ln) >= 0)
@@ -692,7 +691,7 @@ lookup_partial_symbol (struct objfile *objfile,
internal_error (__FILE__, __LINE__,
_("failed internal consistency check"));
if (strcmp_iw_ordered ((*center)->ginfo.search_name (),
- lookup_name.name ().c_str ()) >= 0)
+ lookup_name.c_str ()) >= 0)
{
top = center;
}
diff --git a/gdb/symtab.c b/gdb/symtab.c
index f300d759e03..680280105f5 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -1790,7 +1790,7 @@ demangle_for_lookup_info::demangle_for_lookup_info
if (lookup_name.ignore_parameters () && lang == language_cplus)
{
gdb::unique_xmalloc_ptr<char> without_params
- = cp_remove_params_if_any (lookup_name.name ().c_str (),
+ = cp_remove_params_if_any (lookup_name.c_str (),
lookup_name.completion_mode ());
if (without_params != NULL)
@@ -1803,9 +1803,9 @@ demangle_for_lookup_info::demangle_for_lookup_info
}
if (lookup_name.match_type () == symbol_name_match_type::SEARCH_NAME)
- m_demangled_name = lookup_name.name ();
+ m_demangled_name = lookup_name.c_str ();
else
- m_demangled_name = demangle_for_lookup (lookup_name.name ().c_str (),
+ m_demangled_name = demangle_for_lookup (lookup_name.c_str (),
lang, storage);
}
@@ -1816,7 +1816,7 @@ lookup_name_info::match_any ()
{
/* Lookup any symbol that "" would complete. I.e., this matches all
symbol names. */
- static const lookup_name_info lookup_name ({}, symbol_name_match_type::FULL,
+ static const lookup_name_info lookup_name ("", symbol_name_match_type::FULL,
true);
return lookup_name;
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 771b5ec5bf7..c80acc3a68e 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -186,28 +186,62 @@ class lookup_name_info final
{
public:
/* Create a new object. */
- lookup_name_info (std::string name,
+ lookup_name_info (std::string &&name,
symbol_name_match_type match_type,
bool completion_mode = false,
bool ignore_parameters = false)
: m_match_type (match_type),
m_completion_mode (completion_mode),
m_ignore_parameters (ignore_parameters),
- m_name (std::move (name))
+ m_name_holder (std::move (name)),
+ m_name (m_name_holder.c_str ())
+ {}
+
+ /* This overload requires that NAME have a lifetime at least as long
+ as the lifetime of this object. */
+ lookup_name_info (const std::string &name,
+ symbol_name_match_type match_type,
+ bool completion_mode = false,
+ bool ignore_parameters = false)
+ : m_match_type (match_type),
+ m_completion_mode (completion_mode),
+ m_ignore_parameters (ignore_parameters),
+ m_name (name)
+ {}
+
+ /* This overload requires that NAME have a lifetime at least as long
+ as the lifetime of this object. */
+ lookup_name_info (const char *name,
+ symbol_name_match_type match_type,
+ bool completion_mode = false,
+ bool ignore_parameters = false)
+ : m_match_type (match_type),
+ m_completion_mode (completion_mode),
+ m_ignore_parameters (ignore_parameters),
+ m_name (name)
{}
/* Getters. See description of each corresponding field. */
symbol_name_match_type match_type () const { return m_match_type; }
bool completion_mode () const { return m_completion_mode; }
- const std::string &name () const { return m_name; }
+ gdb::string_view name () const { return m_name; }
const bool ignore_parameters () const { return m_ignore_parameters; }
+ /* Like the "name" method but guarantees that the returned string is
+ \0-terminated. */
+ const char *c_str () const
+ {
+ /* Actually this is always guaranteed due to how the class is
+ constructed. */
+ return m_name.data ();
+ }
+
/* Return a version of this lookup name that is usable with
comparisons against symbols have no parameter info, such as
psymbols and GDB index symbols. */
lookup_name_info make_ignore_params () const
{
- return lookup_name_info (m_name, m_match_type, m_completion_mode,
+ return lookup_name_info (c_str (), m_match_type, m_completion_mode,
true /* ignore params */);
}
@@ -218,27 +252,27 @@ class lookup_name_info final
if (!m_demangled_hashes_p[lang])
{
m_demangled_hashes[lang]
- = ::search_name_hash (lang, language_lookup_name (lang).c_str ());
+ = ::search_name_hash (lang, language_lookup_name (lang));
m_demangled_hashes_p[lang] = true;
}
return m_demangled_hashes[lang];
}
/* Get the search name for searches in language LANG. */
- const std::string &language_lookup_name (language lang) const
+ const char *language_lookup_name (language lang) const
{
switch (lang)
{
case language_ada:
- return ada ().lookup_name ();
+ return ada ().lookup_name ().c_str ();
case language_cplus:
- return cplus ().lookup_name ();
+ return cplus ().lookup_name ().c_str ();
case language_d:
- return d ().lookup_name ();
+ return d ().lookup_name ().c_str ();
case language_go:
- return go ().lookup_name ();
+ return go ().lookup_name ().c_str ();
default:
- return m_name;
+ return m_name.data ();
}
}
@@ -287,7 +321,8 @@ class lookup_name_info final
symbol_name_match_type m_match_type;
bool m_completion_mode;
bool m_ignore_parameters;
- std::string m_name;
+ std::string m_name_holder;
+ gdb::string_view m_name;
/* Language-specific info. These fields are filled lazily the first
time a lookup is done in the corresponding language. They're
--
2.21.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] Avoid copying in lookup_name_info
2020-03-20 20:49 ` [PATCH 2/2] Avoid copying in lookup_name_info Tom Tromey
@ 2020-03-23 17:51 ` Christian Biesinger
2020-03-31 13:28 ` Tom Tromey
2020-03-31 18:18 ` Pedro Alves
1 sibling, 1 reply; 13+ messages in thread
From: Christian Biesinger @ 2020-03-23 17:51 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On Fri, Mar 20, 2020 at 3:49 PM Tom Tromey <tromey@adacore.com> wrote:
>
> lookup_name_info always copies the name that is passed in. However,
> normally a copy is not needed. This patch changes this class to avoid
> copying. This required changing the "name" method to return something
> else; I chose a gdb::string_view, to avoid excessive calls to strlen
> in the code using the lookup_name_info. However, as this class does
> not allow an arbitrary string_view, I've also added a c_str method
> that guarantees a \0-terminated result -- a pedantic difference but
> one that respects the string_view contract, IMO.
>
> gdb/ChangeLog
> 2020-03-20 Tom Tromey <tromey@adacore.com>
>
> * symtab.h (class lookup_name_info) <lookup_name_info>: Change
> "name" parameter to rvalue reference. Initialize m_name_holder.
> <lookup_name_info>: New overloads.
> <name>: Return gdb::string_view.
> <c_str>: New method.
> <make_ignore_params>: Update.
> <search_name_hash>: Update.
> <language_lookup_name>: Return const char *.
> <m_name_holder>: Rename from m_name.
> <m_name>: New member.
> * symtab.c (demangle_for_lookup_info::demangle_for_lookup_info)
> (demangle_for_lookup_info::demangle_for_lookup_info): Update.
> (lookup_name_info::match_any): Update.
> * psymtab.c (match_partial_symbol, lookup_partial_symbol):
> Update.
> * minsyms.c (linkage_name_str): Update.
> * language.c (default_symbol_name_matcher): Update.
> * dwarf2/read.c (mapped_index_base::find_name_components_bounds):
> Update.
> * ada-lang.c (ada_fold_name): Change parameter to string_view.
> (ada_lookup_name_info::ada_lookup_name_info): Update.
> (literal_symbol_name_matcher): Update.
> ---
> gdb/ChangeLog | 25 ++++++++++++++++++++
> gdb/ada-lang.c | 29 ++++++++++++-----------
> gdb/dwarf2/read.c | 2 +-
> gdb/language.c | 4 ++--
> gdb/minsyms.c | 2 +-
> gdb/psymtab.c | 5 ++--
> gdb/symtab.c | 8 +++----
> gdb/symtab.h | 59 +++++++++++++++++++++++++++++++++++++----------
> 8 files changed, 98 insertions(+), 36 deletions(-)
>
> diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
> index 2822d40c8cd..c38ed1fca0e 100644
> --- a/gdb/ada-lang.c
> +++ b/gdb/ada-lang.c
> @@ -1016,17 +1016,17 @@ ada_encode (const char *decoded)
> to next call. */
>
> static char *
> -ada_fold_name (const char *name)
> +ada_fold_name (gdb::string_view name)
> {
> static char *fold_buffer = NULL;
> static size_t fold_buffer_size = 0;
>
> - int len = strlen (name);
> + int len = name.size ();
> GROW_VECT (fold_buffer, fold_buffer_size, len + 1);
>
> if (name[0] == '\'')
> {
> - strncpy (fold_buffer, name + 1, len - 2);
> + strncpy (fold_buffer, name.data () + 1, len - 2);
> fold_buffer[len - 2] = '\000';
> }
> else
> @@ -13953,14 +13953,16 @@ do_exact_match (const char *symbol_search_name,
>
> ada_lookup_name_info::ada_lookup_name_info (const lookup_name_info &lookup_name)
> {
> - const std::string &user_name = lookup_name.name ();
> + gdb::string_view user_name = lookup_name.name ();
>
> if (user_name[0] == '<')
> {
> if (user_name.back () == '>')
> - m_encoded_name = user_name.substr (1, user_name.size () - 2);
> + m_encoded_name
> + = user_name.substr (1, user_name.size () - 2).to_string ();
> else
> - m_encoded_name = user_name.substr (1, user_name.size () - 1);
> + m_encoded_name
> + = user_name.substr (1, user_name.size () - 1).to_string ();
> m_encoded_p = true;
> m_verbatim_p = true;
> m_wild_match_p = false;
> @@ -13970,19 +13972,19 @@ ada_lookup_name_info::ada_lookup_name_info (const lookup_name_info &lookup_name)
> {
> m_verbatim_p = false;
>
> - m_encoded_p = user_name.find ("__") != std::string::npos;
> + m_encoded_p = user_name.find ("__") != gdb::string_view::npos;
>
> if (!m_encoded_p)
> {
> - const char *folded = ada_fold_name (user_name.c_str ());
> + const char *folded = ada_fold_name (user_name);
> const char *encoded = ada_encode_1 (folded, false);
> if (encoded != NULL)
> m_encoded_name = encoded;
> else
> - m_encoded_name = user_name;
> + m_encoded_name = user_name.to_string ();
> }
> else
> - m_encoded_name = user_name;
> + m_encoded_name = user_name.to_string ();
>
> /* Handle the 'package Standard' special case. See description
> of m_standard_p. */
> @@ -14029,11 +14031,12 @@ literal_symbol_name_matcher (const char *symbol_search_name,
> const lookup_name_info &lookup_name,
> completion_match_result *comp_match_res)
> {
> - const std::string &name = lookup_name.name ();
> + gdb::string_view name_view = lookup_name.name ();
> + const char *name = lookup_name.c_str ();
>
> int cmp = (lookup_name.completion_mode ()
> - ? strncmp (symbol_search_name, name.c_str (), name.size ())
> - : strcmp (symbol_search_name, name.c_str ()));
> + ? strncmp (symbol_search_name, name, name_view.size ())
> + : strcmp (symbol_search_name, name));
You can just use symbol_search_name == name_view, since
gdb::string_view has an overloaded operator==. That way you don't need
to call c_str() here.
> if (cmp == 0)
> {
> if (comp_match_res != NULL)
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index 0e879e08a0c..cdccd04c54a 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -3774,7 +3774,7 @@ mapped_index_base::find_name_components_bounds
> = this->name_components_casing == case_sensitive_on ? strcmp : strcasecmp;
>
> const char *lang_name
> - = lookup_name_without_params.language_lookup_name (lang).c_str ();
> + = lookup_name_without_params.language_lookup_name (lang);
>
> /* Comparison function object for lower_bound that matches against a
> given symbol name. */
> diff --git a/gdb/language.c b/gdb/language.c
> index 454c6dc45a7..c13fd1a406a 100644
> --- a/gdb/language.c
> +++ b/gdb/language.c
> @@ -699,14 +699,14 @@ default_symbol_name_matcher (const char *symbol_search_name,
> const lookup_name_info &lookup_name,
> completion_match_result *comp_match_res)
> {
> - const std::string &name = lookup_name.name ();
> + gdb::string_view name = lookup_name.name ();
> completion_match_for_lcd *match_for_lcd
> = (comp_match_res != NULL ? &comp_match_res->match_for_lcd : NULL);
> strncmp_iw_mode mode = (lookup_name.completion_mode ()
> ? strncmp_iw_mode::NORMAL
> : strncmp_iw_mode::MATCH_PARAMS);
>
> - if (strncmp_iw_with_mode (symbol_search_name, name.c_str (), name.size (),
> + if (strncmp_iw_with_mode (symbol_search_name, name.data (), name.size (),
> mode, language_minimal, match_for_lcd) == 0)
> {
> if (comp_match_res != NULL)
> diff --git a/gdb/minsyms.c b/gdb/minsyms.c
> index e238355dc11..d2ac8172eea 100644
> --- a/gdb/minsyms.c
> +++ b/gdb/minsyms.c
> @@ -467,7 +467,7 @@ linkage_name_str (const lookup_name_info &lookup_name)
> if (current_language->la_language == language_ada)
> return lookup_name.ada ().lookup_name ().c_str ();
>
> - return lookup_name.name ().c_str ();
> + return lookup_name.c_str ();
> }
>
> /* See minsyms.h. */
> diff --git a/gdb/psymtab.c b/gdb/psymtab.c
> index 34b9741e966..7ab861632eb 100644
> --- a/gdb/psymtab.c
> +++ b/gdb/psymtab.c
> @@ -612,8 +612,7 @@ match_partial_symbol (struct objfile *objfile,
> gdb_assert (center < top);
>
> enum language lang = (*center)->ginfo.language ();
> - const char *lang_ln
> - = name.language_lookup_name (lang).c_str ();
> + const char *lang_ln = name.language_lookup_name (lang);
>
> if (ordered_compare ((*center)->ginfo.search_name (),
> lang_ln) >= 0)
> @@ -692,7 +691,7 @@ lookup_partial_symbol (struct objfile *objfile,
> internal_error (__FILE__, __LINE__,
> _("failed internal consistency check"));
> if (strcmp_iw_ordered ((*center)->ginfo.search_name (),
> - lookup_name.name ().c_str ()) >= 0)
> + lookup_name.c_str ()) >= 0)
> {
> top = center;
> }
> diff --git a/gdb/symtab.c b/gdb/symtab.c
> index f300d759e03..680280105f5 100644
> --- a/gdb/symtab.c
> +++ b/gdb/symtab.c
> @@ -1790,7 +1790,7 @@ demangle_for_lookup_info::demangle_for_lookup_info
> if (lookup_name.ignore_parameters () && lang == language_cplus)
> {
> gdb::unique_xmalloc_ptr<char> without_params
> - = cp_remove_params_if_any (lookup_name.name ().c_str (),
> + = cp_remove_params_if_any (lookup_name.c_str (),
> lookup_name.completion_mode ());
>
> if (without_params != NULL)
> @@ -1803,9 +1803,9 @@ demangle_for_lookup_info::demangle_for_lookup_info
> }
>
> if (lookup_name.match_type () == symbol_name_match_type::SEARCH_NAME)
> - m_demangled_name = lookup_name.name ();
> + m_demangled_name = lookup_name.c_str ();
> else
> - m_demangled_name = demangle_for_lookup (lookup_name.name ().c_str (),
> + m_demangled_name = demangle_for_lookup (lookup_name.c_str (),
> lang, storage);
> }
>
> @@ -1816,7 +1816,7 @@ lookup_name_info::match_any ()
> {
> /* Lookup any symbol that "" would complete. I.e., this matches all
> symbol names. */
> - static const lookup_name_info lookup_name ({}, symbol_name_match_type::FULL,
> + static const lookup_name_info lookup_name ("", symbol_name_match_type::FULL,
> true);
>
> return lookup_name;
> diff --git a/gdb/symtab.h b/gdb/symtab.h
> index 771b5ec5bf7..c80acc3a68e 100644
> --- a/gdb/symtab.h
> +++ b/gdb/symtab.h
> @@ -186,28 +186,62 @@ class lookup_name_info final
> {
> public:
> /* Create a new object. */
> - lookup_name_info (std::string name,
> + lookup_name_info (std::string &&name,
> symbol_name_match_type match_type,
> bool completion_mode = false,
> bool ignore_parameters = false)
> : m_match_type (match_type),
> m_completion_mode (completion_mode),
> m_ignore_parameters (ignore_parameters),
> - m_name (std::move (name))
> + m_name_holder (std::move (name)),
> + m_name (m_name_holder.c_str ())
> + {}
> +
> + /* This overload requires that NAME have a lifetime at least as long
> + as the lifetime of this object. */
> + lookup_name_info (const std::string &name,
> + symbol_name_match_type match_type,
> + bool completion_mode = false,
> + bool ignore_parameters = false)
> + : m_match_type (match_type),
> + m_completion_mode (completion_mode),
> + m_ignore_parameters (ignore_parameters),
> + m_name (name)
> + {}
> +
> + /* This overload requires that NAME have a lifetime at least as long
> + as the lifetime of this object. */
> + lookup_name_info (const char *name,
> + symbol_name_match_type match_type,
> + bool completion_mode = false,
> + bool ignore_parameters = false)
> + : m_match_type (match_type),
> + m_completion_mode (completion_mode),
> + m_ignore_parameters (ignore_parameters),
> + m_name (name)
> {}
>
> /* Getters. See description of each corresponding field. */
> symbol_name_match_type match_type () const { return m_match_type; }
> bool completion_mode () const { return m_completion_mode; }
> - const std::string &name () const { return m_name; }
> + gdb::string_view name () const { return m_name; }
> const bool ignore_parameters () const { return m_ignore_parameters; }
>
> + /* Like the "name" method but guarantees that the returned string is
> + \0-terminated. */
> + const char *c_str () const
> + {
> + /* Actually this is always guaranteed due to how the class is
> + constructed. */
> + return m_name.data ();
> + }
> +
> /* Return a version of this lookup name that is usable with
> comparisons against symbols have no parameter info, such as
> psymbols and GDB index symbols. */
> lookup_name_info make_ignore_params () const
> {
> - return lookup_name_info (m_name, m_match_type, m_completion_mode,
> + return lookup_name_info (c_str (), m_match_type, m_completion_mode,
> true /* ignore params */);
> }
>
> @@ -218,27 +252,27 @@ class lookup_name_info final
> if (!m_demangled_hashes_p[lang])
> {
> m_demangled_hashes[lang]
> - = ::search_name_hash (lang, language_lookup_name (lang).c_str ());
> + = ::search_name_hash (lang, language_lookup_name (lang));
> m_demangled_hashes_p[lang] = true;
> }
> return m_demangled_hashes[lang];
> }
>
> /* Get the search name for searches in language LANG. */
> - const std::string &language_lookup_name (language lang) const
> + const char *language_lookup_name (language lang) const
> {
> switch (lang)
> {
> case language_ada:
> - return ada ().lookup_name ();
> + return ada ().lookup_name ().c_str ();
> case language_cplus:
> - return cplus ().lookup_name ();
> + return cplus ().lookup_name ().c_str ();
> case language_d:
> - return d ().lookup_name ();
> + return d ().lookup_name ().c_str ();
> case language_go:
> - return go ().lookup_name ();
> + return go ().lookup_name ().c_str ();
> default:
> - return m_name;
> + return m_name.data ();
> }
> }
>
> @@ -287,7 +321,8 @@ class lookup_name_info final
> symbol_name_match_type m_match_type;
> bool m_completion_mode;
> bool m_ignore_parameters;
> - std::string m_name;
> + std::string m_name_holder;
> + gdb::string_view m_name;
>
> /* Language-specific info. These fields are filled lazily the first
> time a lookup is done in the corresponding language. They're
> --
> 2.21.1
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] Avoid copying in lookup_name_info
2020-03-23 17:51 ` Christian Biesinger
@ 2020-03-31 13:28 ` Tom Tromey
0 siblings, 0 replies; 13+ messages in thread
From: Tom Tromey @ 2020-03-31 13:28 UTC (permalink / raw)
To: Christian Biesinger; +Cc: Tom Tromey, gdb-patches
>>>>> "Christian" == Christian Biesinger <cbiesinger@google.com> writes:
>> int cmp = (lookup_name.completion_mode ()
>> - ? strncmp (symbol_search_name, name.c_str (), name.size ())
>> - : strcmp (symbol_search_name, name.c_str ()));
>> + ? strncmp (symbol_search_name, name, name_view.size ())
>> + : strcmp (symbol_search_name, name));
Christian> You can just use symbol_search_name == name_view, since
Christian> gdb::string_view has an overloaded operator==. That way you don't need
Christian> to call c_str() here.
Thanks, I made this change. I removed "cmp" as well, so now it looks
like:
if (lookup_name.completion_mode ()
? (strncmp (symbol_search_name, name_view.data (),
name_view.size ()) == 0)
: symbol_search_name == name_view)
C++20 has a starts_with method on string view, but we don't have that
yet.
Tom
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] Avoid some copying in psymtab.c
2020-03-20 20:49 ` [PATCH 1/2] Avoid some copying in psymtab.c Tom Tromey
@ 2020-03-31 17:46 ` Pedro Alves
2020-03-31 19:35 ` Tom Tromey
0 siblings, 1 reply; 13+ messages in thread
From: Pedro Alves @ 2020-03-31 17:46 UTC (permalink / raw)
To: Tom Tromey, gdb-patches
On 3/20/20 8:49 PM, Tom Tromey wrote:
> + psymtab_search_name search_name (name);
> + lookup_name_info psym_lookup_name (search_name.get (),
> + symbol_name_match_type::FULL);
> +
lookup_name_info has built-in support for psymtab-style symbol
names, with no parameter info. See psym_expand_symtabs_matching:
lookup_name_info lookup_name = lookup_name_in.make_ignore_params ();
I think doing the same in psym_lookup_symbol is likely to work
just the same, and avoid this new class.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] Avoid copying in lookup_name_info
2020-03-20 20:49 ` [PATCH 2/2] Avoid copying in lookup_name_info Tom Tromey
2020-03-23 17:51 ` Christian Biesinger
@ 2020-03-31 18:18 ` Pedro Alves
2020-03-31 19:11 ` Tom Tromey
1 sibling, 1 reply; 13+ messages in thread
From: Pedro Alves @ 2020-03-31 18:18 UTC (permalink / raw)
To: Tom Tromey, gdb-patches
On 3/20/20 8:49 PM, Tom Tromey wrote:
> return lookup_name;
> diff --git a/gdb/symtab.h b/gdb/symtab.h
> index 771b5ec5bf7..c80acc3a68e 100644
> --- a/gdb/symtab.h
> +++ b/gdb/symtab.h
> @@ -186,28 +186,62 @@ class lookup_name_info final
> {
> public:
> /* Create a new object. */
> - lookup_name_info (std::string name,
> + lookup_name_info (std::string &&name,
> symbol_name_match_type match_type,
> bool completion_mode = false,
> bool ignore_parameters = false)
> : m_match_type (match_type),
> m_completion_mode (completion_mode),
> m_ignore_parameters (ignore_parameters),
> - m_name (std::move (name))
> + m_name_holder (std::move (name)),
> + m_name (m_name_holder.c_str ())
> + {}
> +
> + /* This overload requires that NAME have a lifetime at least as long
> + as the lifetime of this object. */
> + lookup_name_info (const std::string &name,
I think it would be better for this overload to take a
gdb::string_view instead of a const std::string& . That
way, it still works if you only have a string_view handy.
As is, there's no way to created a lookup_name_info starting
with a string_view without copying. WDYT?
And if we do that, do we have any case where we really need the
"std::string &&" overload? You mention that normally copying
isn't needed -- but when is copying needed? I.e., do we have
cases where the lookup_name_info object doesn't have a lifetime greater
than the original string? If there isn't, then we could also get
rid of name_holder, and avoid having to remember that different
ctors behave differently.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] Avoid copying in lookup_name_info
2020-03-31 18:18 ` Pedro Alves
@ 2020-03-31 19:11 ` Tom Tromey
2020-03-31 19:15 ` Tom Tromey
2020-03-31 19:23 ` Pedro Alves
0 siblings, 2 replies; 13+ messages in thread
From: Tom Tromey @ 2020-03-31 19:11 UTC (permalink / raw)
To: Pedro Alves; +Cc: Tom Tromey, gdb-patches
>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
Pedro> I think it would be better for this overload to take a
Pedro> gdb::string_view instead of a const std::string& . That
Pedro> way, it still works if you only have a string_view handy.
Pedro> As is, there's no way to created a lookup_name_info starting
Pedro> with a string_view without copying. WDYT?
The issue is that there's a trick in the implementation:
/* Like the "name" method but guarantees that the returned string is
\0-terminated. */
const char *c_str () const
{
/* Actually this is always guaranteed due to how the class is
constructed. */
return m_name.data ();
}
This is needed in some spots.
However, if we take a string_view at construction, then we'd be
violating the string_view contract, or we'd need to make a copy -- but
the former is bad, and the latter is the goal the patch.
Pedro> And if we do that, do we have any case where we really need the
Pedro> "std::string &&" overload?
Indeed we don't seem to need this.
Tom
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] Avoid copying in lookup_name_info
2020-03-31 19:11 ` Tom Tromey
@ 2020-03-31 19:15 ` Tom Tromey
2020-03-31 19:28 ` Pedro Alves
2020-03-31 19:23 ` Pedro Alves
1 sibling, 1 reply; 13+ messages in thread
From: Tom Tromey @ 2020-03-31 19:15 UTC (permalink / raw)
To: Tom Tromey; +Cc: Pedro Alves, gdb-patches
>>>>> "Tom" == Tom Tromey <tromey@adacore.com> writes:
Pedro> And if we do that, do we have any case where we really need the
Pedro> "std::string &&" overload?
Tom> Indeed we don't seem to need this.
Actually, I am wrong, there is a spot in ada-lang.c:
lookup_name_info name1 (std::string ("<_ada_") + name + '>',
symbol_name_match_type::FULL);
What's concerning is that this compiles even without the && overload,
presumably by just violating the lifetime requirement of lookup_name_info.
So, I think leaving the && version in-place is best.
Tom
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] Avoid copying in lookup_name_info
2020-03-31 19:11 ` Tom Tromey
2020-03-31 19:15 ` Tom Tromey
@ 2020-03-31 19:23 ` Pedro Alves
1 sibling, 0 replies; 13+ messages in thread
From: Pedro Alves @ 2020-03-31 19:23 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 3/31/20 8:11 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
>
> Pedro> I think it would be better for this overload to take a
> Pedro> gdb::string_view instead of a const std::string& . That
> Pedro> way, it still works if you only have a string_view handy.
> Pedro> As is, there's no way to created a lookup_name_info starting
> Pedro> with a string_view without copying. WDYT?
>
> The issue is that there's a trick in the implementation:
>
> /* Like the "name" method but guarantees that the returned string is
> \0-terminated. */
> const char *c_str () const
> {
> /* Actually this is always guaranteed due to how the class is
> constructed. */
> return m_name.data ();
> }
>
> This is needed in some spots.
>
> However, if we take a string_view at construction, then we'd be
> violating the string_view contract, or we'd need to make a copy -- but
> the former is bad, and the latter is the goal the patch.
I see. I agree with leaving it as is then.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] Avoid copying in lookup_name_info
2020-03-31 19:15 ` Tom Tromey
@ 2020-03-31 19:28 ` Pedro Alves
2020-03-31 19:35 ` Tom Tromey
0 siblings, 1 reply; 13+ messages in thread
From: Pedro Alves @ 2020-03-31 19:28 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 3/31/20 8:15 PM, Tom Tromey wrote:
>>>>>> "Tom" == Tom Tromey <tromey@adacore.com> writes:
>
> Pedro> And if we do that, do we have any case where we really need the
> Pedro> "std::string &&" overload?
>
> Tom> Indeed we don't seem to need this.
>
> Actually, I am wrong, there is a spot in ada-lang.c:
>
> lookup_name_info name1 (std::string ("<_ada_") + name + '>',
> symbol_name_match_type::FULL);
>
> What's concerning is that this compiles even without the && overload,
> presumably by just violating the lifetime requirement of lookup_name_info.
>
> So, I think leaving the && version in-place is best.
Alternatively, you could delete the && version, like:
lookup_name_info (std::string &&name, ......) = delete;
I think that would catch that case, making it fail to compile,
forcing us to write:
std::string str = std::string ("<_ada_") + name + '>';
lookup_name_info name1 (str, symbol_name_match_type::FULL);
I think I'd slightly prefer that for making lookup_name_info's
contract easier to grok, though I'll leave it to you.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] Avoid copying in lookup_name_info
2020-03-31 19:28 ` Pedro Alves
@ 2020-03-31 19:35 ` Tom Tromey
0 siblings, 0 replies; 13+ messages in thread
From: Tom Tromey @ 2020-03-31 19:35 UTC (permalink / raw)
To: Pedro Alves; +Cc: Tom Tromey, gdb-patches
>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
Pedro> Alternatively, you could delete the && version, like:
Pedro> lookup_name_info (std::string &&name, ......) = delete;
Pedro> I think that would catch that case, making it fail to compile,
Pedro> forcing us to write:
Thanks for the idea. I'll do this.
Tom
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] Avoid some copying in psymtab.c
2020-03-31 17:46 ` Pedro Alves
@ 2020-03-31 19:35 ` Tom Tromey
0 siblings, 0 replies; 13+ messages in thread
From: Tom Tromey @ 2020-03-31 19:35 UTC (permalink / raw)
To: Pedro Alves; +Cc: Tom Tromey, gdb-patches
>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
Pedro> lookup_name_info has built-in support for psymtab-style symbol
Pedro> names, with no parameter info. See psym_expand_symtabs_matching:
Pedro> lookup_name_info lookup_name = lookup_name_in.make_ignore_params ();
Pedro> I think doing the same in psym_lookup_symbol is likely to work
Pedro> just the same, and avoid this new class.
I knew about this but somehow I thought it only worked "one way".
But, I've tried it and as far as I can tell it works fine and it
simplifies the code, so I've made this change.
Tom
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2020-03-31 19:35 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-20 20:49 [PATCH 0/2] Avoid copying in name lookup Tom Tromey
2020-03-20 20:49 ` [PATCH 1/2] Avoid some copying in psymtab.c Tom Tromey
2020-03-31 17:46 ` Pedro Alves
2020-03-31 19:35 ` Tom Tromey
2020-03-20 20:49 ` [PATCH 2/2] Avoid copying in lookup_name_info Tom Tromey
2020-03-23 17:51 ` Christian Biesinger
2020-03-31 13:28 ` Tom Tromey
2020-03-31 18:18 ` Pedro Alves
2020-03-31 19:11 ` Tom Tromey
2020-03-31 19:15 ` Tom Tromey
2020-03-31 19:28 ` Pedro Alves
2020-03-31 19:35 ` Tom Tromey
2020-03-31 19:23 ` Pedro Alves
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox