This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]