Fix TAB-completion + .gdb_index slowness (generalize filename_seen_cache)
[deliverable/binutils-gdb.git] / gdb / dwarf2read.c
index b690d0b30e2a8a191f3532fe2b137e968c6a1d79..bb69f44f463fd1aca1104e7a9cb1ddd32cc37e8e 100644 (file)
@@ -74,7 +74,7 @@
 #include "common/gdb_optional.h"
 #include "common/underlying.h"
 #include "common/byte-vector.h"
-
+#include "filename-seen-cache.h"
 #include <fcntl.h>
 #include <sys/types.h>
 #include <algorithm>
@@ -349,6 +349,10 @@ public:
 
   /* Table containing line_header indexed by offset and offset_in_dwz.  */
   htab_t line_header_hash {};
+
+  /* Table containing all filenames.  This is an optional because the
+     table is lazily constructed on first access.  */
+  gdb::optional<filename_seen_cache> filenames_cache;
 };
 
 static struct dwarf2_per_objfile *dwarf2_per_objfile;
@@ -4312,64 +4316,75 @@ static void
 dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
                          void *data, int need_fullname)
 {
-  int i;
-  htab_up visited (htab_create_alloc (10, htab_hash_pointer, htab_eq_pointer,
-                                     NULL, xcalloc, xfree));
-
   dw2_setup (objfile);
 
-  /* The rule is CUs specify all the files, including those used by
-     any TU, so there's no need to scan TUs here.
-     We can ignore file names coming from already-expanded CUs.  */
-
-  for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+  if (!dwarf2_per_objfile->filenames_cache)
     {
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
+      dwarf2_per_objfile->filenames_cache.emplace ();
 
-      if (per_cu->v.quick->compunit_symtab)
-       {
-         void **slot = htab_find_slot (visited.get (),
-                                       per_cu->v.quick->file_names,
-                                       INSERT);
+      htab_up visited (htab_create_alloc (10,
+                                         htab_hash_pointer, htab_eq_pointer,
+                                         NULL, xcalloc, xfree));
 
-         *slot = per_cu->v.quick->file_names;
-       }
-    }
-
-  for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
-    {
-      int j;
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
-      struct quick_file_names *file_data;
-      void **slot;
+      /* The rule is CUs specify all the files, including those used
+        by any TU, so there's no need to scan TUs here.  We can
+        ignore file names coming from already-expanded CUs.  */
 
-      /* We only need to look at symtabs not already expanded.  */
-      if (per_cu->v.quick->compunit_symtab)
-       continue;
+      for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+       {
+         struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
 
-      file_data = dw2_get_file_names (per_cu);
-      if (file_data == NULL)
-       continue;
+         if (per_cu->v.quick->compunit_symtab)
+           {
+             void **slot = htab_find_slot (visited.get (),
+                                           per_cu->v.quick->file_names,
+                                           INSERT);
 
-      slot = htab_find_slot (visited.get (), file_data, INSERT);
-      if (*slot)
-       {
-         /* Already visited.  */
-         continue;
+             *slot = per_cu->v.quick->file_names;
+           }
        }
-      *slot = file_data;
 
-      for (j = 0; j < file_data->num_file_names; ++j)
+      for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
        {
-         const char *this_real_name;
+         int j;
+         struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+         struct quick_file_names *file_data;
+         void **slot;
 
-         if (need_fullname)
-           this_real_name = dw2_get_real_path (objfile, file_data, j);
-         else
-           this_real_name = NULL;
-         (*fun) (file_data->file_names[j], this_real_name, data);
+         /* We only need to look at symtabs not already expanded.  */
+         if (per_cu->v.quick->compunit_symtab)
+           continue;
+
+         file_data = dw2_get_file_names (per_cu);
+         if (file_data == NULL)
+           continue;
+
+         slot = htab_find_slot (visited.get (), file_data, INSERT);
+         if (*slot)
+           {
+             /* Already visited.  */
+             continue;
+           }
+         *slot = file_data;
+
+         for (int j = 0; j < file_data->num_file_names; ++j)
+           {
+             const char *filename = file_data->file_names[j];
+             dwarf2_per_objfile->filenames_cache->seen (filename);
+           }
        }
     }
+
+  dwarf2_per_objfile->filenames_cache->traverse ([&] (const char *filename)
+    {
+      const char *this_real_name;
+
+      if (need_fullname)
+       this_real_name = gdb_realpath (filename);
+      else
+       this_real_name = NULL;
+      (*fun) (filename, this_real_name, data);
+    });
 }
 
 static int
This page took 0.03171 seconds and 4 git commands to generate.