This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFA] special case (anonymous namespace)::foo in linespec.c
- From: Doug Evans <dje at google dot com>
- To: gdb-patches at sourceware dot org
- Date: Fri, 01 Feb 2013 16:58:58 -0800
- Subject: [RFA] special case (anonymous namespace)::foo in linespec.c
Hi.
I'd like to check this patch in.
It improves the time to do "break (anonymous namespace)::foo"
in some large apps from 100s of seconds to a few seconds (or less).
[This is with .gdb_index.]
The code calls lookup_prefix_sym to find the set of symtabs that
define the "foo" in "foo::bar". This is important in the case of
classes because bar may be in a baseclass of foo.
However, we don't need to do this if foo is a namespace. However,
we don't know if foo is a namespace or a class until we expand the CU.
[Unnecessarily expanding CUs is what the index is there to prevent.]
Things are further complicated by the fact that
foo may be a namespace in one CU and, say, a typedef of a class
in another CU. So we have to expand every CU defining something
from foo. Ugh.
[I think we should extend the index to fix this, but I haven't
looked into this much yet.]
The exception is (anonymous namespace). Here we don't have to
call lookup_prefix_sym, and can always just lookup the complete symbol.
Ok to check in?
2013-01-31 Doug Evans <dje@google.com>
* linespec.c (find_linespec_symbols): New local have_anon_ns.
Avoid calling lookup_prefix_sym for
[foo::](anonymous namespace)::bar.
Index: linespec.c
===================================================================
RCS file: /cvs/src/src/gdb/linespec.c,v
retrieving revision 1.175
diff -u -p -r1.175 linespec.c
--- linespec.c 23 Jan 2013 20:07:39 -0000 1.175
+++ linespec.c 2 Feb 2013 00:38:54 -0000
@@ -2958,7 +2958,7 @@ find_linespec_symbols (struct linespec_s
char *klass, *method, *canon;
const char *lookup_name, *last, *p, *scope_op;
struct cleanup *cleanup;
- VEC (symbolp) *classes;
+ int have_anon_ns;
volatile struct gdb_exception except;
cleanup = demangle_for_lookup (name, state->language->la_language,
@@ -3018,33 +3018,68 @@ find_linespec_symbols (struct linespec_s
make_cleanup (xfree, method);
strcpy (method, last);
- /* Find a list of classes named KLASS. */
- classes = lookup_prefix_sym (state, file_symtabs, klass);
- make_cleanup (VEC_cleanup (symbolp), &classes);
- if (!VEC_empty (symbolp, classes))
+ /* It's important to not call expand_symtabs_matching unnecessarily
+ as it can really slow things down (by unnecessarily expanding
+ potentially 1000s of symtabs). If we know we only want classes,
+ we'd like to skip symtabs where NAME isn't a class. However,
+ NAME could be a class in some symtabs and a namespace in others,
+ and we can't tell which until we expand the symtab! Ugh!
+ What we need is for "quick" symbols (partial syms and .gdb_index)
+ to at least record whether a symbol is a class. Until then, there's
+ not much we can do. One thing we can do is watch for "(anonymous
+ namespace)" which is actually significant enough to warrant it.
+ That will at least handle "b [foo::](anonymous namespace)::bar".
+ In some apps this can speed up the time to set the breakpoint from
+ 100s of seconds to a few seconds. */
+ have_anon_ns = 0;
+ if (state->language->la_language == language_cplus)
+ {
+ int scope_op_len = strlen (scope_op);
+
+ /* Find the segment of KLASS. */
+ p = strrchr (klass, scope_op[scope_op_len - 1]);
+ if (p != NULL)
+ ++p;
+ else
+ p = klass;
+
+ if (strcmp_iw (klass, CP_ANONYMOUS_NAMESPACE_STR) == 0)
+ have_anon_ns = 1;
+ }
+
+ if (! have_anon_ns)
{
- /* Now locate a list of suitable methods named METHOD. */
- TRY_CATCH (except, RETURN_MASK_ERROR)
- {
- find_method (state, file_symtabs, klass, method, classes,
- symbols, minsyms);
- }
+ VEC (symbolp) *classes;
+
+ /* Find a list of classes named KLASS. */
+ classes = lookup_prefix_sym (state, file_symtabs, klass);
+ make_cleanup (VEC_cleanup (symbolp), &classes);
- /* If successful, we're done. If NOT_FOUND_ERROR
- was not thrown, rethrow the exception that we did get.
- Otherwise, fall back to looking up the entire name as a symbol.
- This can happen with namespace::function. */
- if (except.reason >= 0)
+ if (!VEC_empty (symbolp, classes))
{
- do_cleanups (cleanup);
- return;
+ /* Now locate a list of suitable methods named METHOD. */
+ TRY_CATCH (except, RETURN_MASK_ERROR)
+ {
+ find_method (state, file_symtabs, klass, method, classes,
+ symbols, minsyms);
+ }
+
+ /* If successful, we're done. If NOT_FOUND_ERROR
+ was not thrown, rethrow the exception that we did get.
+ Otherwise, fall back to looking up the entire name as a symbol.
+ This can happen with namespace::function. */
+ if (except.reason >= 0)
+ {
+ do_cleanups (cleanup);
+ return;
+ }
+ else if (except.error != NOT_FOUND_ERROR)
+ throw_exception (except);
}
- else if (except.error != NOT_FOUND_ERROR)
- throw_exception (except);
}
- /* We couldn't find a class, so we check the entire name as a symbol
- instead. */
+ /* We couldn't find klass, or we did but it's the anonymous namespace,
+ so check the entire name as a symbol instead. */
find_function_symbols (state, file_symtabs, lookup_name, symbols, minsyms);
do_cleanups (cleanup);
}