* bcache.c, bcache.h: New files to implement a byte cache.
authorFred Fish <fnf@specifix.com>
Fri, 16 Feb 1996 22:14:47 +0000 (22:14 +0000)
committerFred Fish <fnf@specifix.com>
Fri, 16 Feb 1996 22:14:47 +0000 (22:14 +0000)
* Makefile.in (SFILES): Add bcache.c.
(symtab_h): Add bcache.h.
(HFILES_NO_SRCDIR): add bcache.h
(COMMON_OBJS): Add bcache.o
(bcache.o): New target.
* dbxread.c (start_psymtab): Make global_syms & static_syms
  type "partial_symbol **".
* hpread.c (hpread_start_symtab):  Ditto.
* os9kread.c (os9k_start_psymtab):  Ditto.
* stabsread.h (start_psymtab):  Ditto.
* {symfile.c, symfile.h} (start_psymtab_common):  Ditto.
* maint.c (maintenance_print_statistics): Call
  print_symbol_bcache_statistics.
* objfiles.c (allocate_objfile): Initialize psymbol bcache malloc
and free pointers.
* solib.c (allocate_rt_common_objfile): Ditto.
* symfile.c (reread_symbols):  Ditto.
(free_objfile): Free psymbol bcache when objfile is freed.
(objfile_relocate): Use new indirect psymbol pointers.
* objfiles.h (struct objfile): Add psymbol cache.
* symfile.c (compare_psymbols): Now passed pointers to pointers to
psymbols.
(reread_symbols): Free psymbol bcache when freeing other objfile
resources.
(add_psymbol_to_list, add_psymbol_addr_to_list): Initialize new
psymbol using the psymbol bcache.
(init_psymbol_list): Psymbol lists now contain pointers rather than
the actual psymbols.
* symfile.h (psymbol_allocation_list): Psymbol lists now dynamically
grown arrays of pointers.
(ADD_PSYMBOL_VT_TO_LIST): Initialize new symbol using the psymbol
bcache.
* symmisc.c (print_partial_symbols): Now takes pointer to pointer
to partial symbol.
(print_symbol_bcache_statistics): New function to print per objfile
  bcache statistics.
(print_partial_symbol, print_partial_symbols,
  maintenance_check_symtabs, extend_psymbol_list):
  Account for change to pointer to pointer to partial symbol.
* symtab.c (find_pc_psymbol, lookup_partial_symbol, decode_line_2,
make_symbol_completion_list):
  Account for change to pointer to pointer to partial symbol.
* symtab.h (bcache.h): Include.
* xcoffread.c (xcoff_start_psymtab): Make global_syms & static_syms
  type "partial_symbol **".

16 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/NEWS
gdb/bcache.c [new file with mode: 0644]
gdb/bcache.h [new file with mode: 0644]
gdb/hpread.c
gdb/maint.c
gdb/objfiles.c
gdb/objfiles.h
gdb/os9kread.c
gdb/stabsread.h
gdb/symfile.c
gdb/symfile.h
gdb/symmisc.c
gdb/symtab.h
gdb/xcoffread.c

index b2f631d..1310795 100644 (file)
@@ -1,3 +1,52 @@
+Fri Feb 16 14:00:54 1996  Fred Fish  <fnf@cygnus.com>
+
+       * bcache.c, bcache.h: New files to implement a byte cache.
+       * Makefile.in (SFILES): Add bcache.c.
+       (symtab_h): Add bcache.h.
+       (HFILES_NO_SRCDIR): add bcache.h
+       (COMMON_OBJS): Add bcache.o
+       (bcache.o): New target.
+       * dbxread.c (start_psymtab): Make global_syms & static_syms
+       type "partial_symbol **".
+       * hpread.c (hpread_start_symtab):  Ditto.
+       * os9kread.c (os9k_start_psymtab):  Ditto.
+       * stabsread.h (start_psymtab):  Ditto.
+       * {symfile.c, symfile.h} (start_psymtab_common):  Ditto.
+       * maint.c (maintenance_print_statistics): Call
+       print_symbol_bcache_statistics.
+       * objfiles.c (allocate_objfile): Initialize psymbol bcache malloc
+       and free pointers.
+       * solib.c (allocate_rt_common_objfile): Ditto.
+       * symfile.c (reread_symbols):  Ditto.
+       (free_objfile): Free psymbol bcache when objfile is freed.      
+       (objfile_relocate): Use new indirect psymbol pointers.
+       * objfiles.h (struct objfile): Add psymbol cache.
+       * symfile.c (compare_psymbols): Now passed pointers to pointers to
+       psymbols.
+       (reread_symbols): Free psymbol bcache when freeing other objfile
+       resources.
+       (add_psymbol_to_list, add_psymbol_addr_to_list): Initialize new
+       psymbol using the psymbol bcache.
+       (init_psymbol_list): Psymbol lists now contain pointers rather than
+       the actual psymbols.
+       * symfile.h (psymbol_allocation_list): Psymbol lists now dynamically
+       grown arrays of pointers.
+       (ADD_PSYMBOL_VT_TO_LIST): Initialize new symbol using the psymbol
+       bcache.
+       * symmisc.c (print_partial_symbols): Now takes pointer to pointer
+       to partial symbol.
+       (print_symbol_bcache_statistics): New function to print per objfile
+       bcache statistics.
+       (print_partial_symbol, print_partial_symbols,
+       maintenance_check_symtabs, extend_psymbol_list):
+       Account for change to pointer to pointer to partial symbol.
+       * symtab.c (find_pc_psymbol, lookup_partial_symbol, decode_line_2,
+       make_symbol_completion_list): 
+       Account for change to pointer to pointer to partial symbol.
+       * symtab.h (bcache.h): Include.
+       * xcoffread.c (xcoff_start_psymtab): Make global_syms & static_syms
+       type "partial_symbol **".
+
 Fri Feb 16 10:02:34 1996  Fred Fish  <fnf@cygnus.com>
 
        * dwarfread.c (free_utypes): New function.
index 51d8e38..e1167cb 100644 (file)
@@ -145,7 +145,6 @@ ENABLE_CFLAGS= @ENABLE_CFLAGS@
 ENABLE_CLIBS= @ENABLE_CLIBS@
 ENABLE_OBS= @ENABLE_OBS@
 
-
 # -I. for config files.
 # -I$(srcdir) for gdb internal headers and possibly for gnu-regex.h also.
 # -I$(srcdir)/config for more generic config files.
@@ -197,10 +196,11 @@ REGEX1 = gnu-regex.o
 # If you have the Cygnus libraries installed,
 # you can use 'CLIBS=$(INSTALLED_LIBS)' 'CDEPS='
 INSTALLED_LIBS=-lbfd -lreadline $(TERMCAP) -lopcodes -lmmalloc \
-       -liberty $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(ENABLE_CLIBS)
+       -liberty $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(ENABLE_CLIBS) \
+       @LIBS@
 CLIBS = $(SIM) $(BFD) $(READLINE) $(OPCODES) $(MMALLOC) $(LIBIBERTY) \
        $(ENABLE_CLIBS) $(TERMCAP) $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) \
-       $(LIBIBERTY) $(LIBS)
+       $(LIBIBERTY) @LIBS@
 CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE) \
        $(OPCODES) $(MMALLOC) $(LIBIBERTY)
 
@@ -345,10 +345,10 @@ TARGET_FLAGS_TO_PASS = \
 # Links made at configuration time should not be specified here, since
 # SFILES is used in building the distribution archive.
 
-SFILES = blockframe.c breakpoint.c buildsym.c callback.c c-exp.y c-lang.c \
-       c-typeprint.c c-valprint.c ch-exp.c ch-lang.c ch-typeprint.c \
-       ch-valprint.c coffread.c command.c complaints.c corefile.c cp-valprint.c \
-       dbxread.c demangle.c dwarfread.c \
+SFILES = bcache.c blockframe.c breakpoint.c buildsym.c callback.c c-exp.y \
+       c-lang.c c-typeprint.c c-valprint.c ch-exp.c ch-lang.c \
+       ch-typeprint.c ch-valprint.c coffread.c command.c complaints.c \
+       corefile.c cp-valprint.c dbxread.c demangle.c dwarfread.c \
        elfread.c environ.c eval.c expprint.c \
        f-exp.y f-lang.c f-typeprint.c f-valprint.c findvar.c \
        gdbtypes.c infcmd.c inflow.c infrun.c language.c \
@@ -393,7 +393,7 @@ udiheaders = \
 gdbcore_h =    gdbcore.h $(bfd_h)
 
 frame_h =      frame.h
-symtab_h =     symtab.h
+symtab_h =     symtab.h bcache.h
 gdbtypes_h =   gdbtypes.h
 expression_h = expression.h
 value_h =      value.h $(symtab_h) $(gdbtypes_h) $(expression_h)
@@ -413,8 +413,8 @@ inferior_h =        inferior.h $(breakpoint_h)
 # wrong if TAGS has files twice).  Because this is tricky to get
 # right, it is probably easiest just to list .h files here directly.
 
-HFILES_NO_SRCDIR = buildsym.h call-cmds.h coff-solib.h defs.h dst.h environ.h \
-       $(gdbcmd_h) gdbcore.h \
+HFILES_NO_SRCDIR = bcache.h buildsym.h call-cmds.h coff-solib.h defs.h \
+       dst.h environ.h $(gdbcmd_h) gdbcore.h \
        gdb-stabs.h $(inferior_h) language.h minimon.h monitor.h \
        objfiles.h parser-defs.h partial-stab.h serial.h signals.h solib.h \
        symfile.h stabsread.h target.h terminal.h typeprint.h xcoffsolib.h \
@@ -461,7 +461,7 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o stack.o thread.o \
        symtab.o symfile.o symmisc.o infcmd.o infrun.o command.o \
        expprint.o environ.o gdbtypes.o copying.o $(DEPFILES) \
        mem-break.o target.o parse.o language.o $(YYOBJ) buildsym.o \
-       exec.o objfiles.o minsyms.o maint.o demangle.o \
+       exec.o bcache.o objfiles.o minsyms.o maint.o demangle.o \
        dbxread.o coffread.o elfread.o \
        dwarfread.o mipsread.o stabsread.o corefile.o \
        c-lang.o ch-exp.o ch-lang.o f-lang.o m2-lang.o \
@@ -743,7 +743,7 @@ maintainer-clean realclean: clean
        rm -f Makefile
 
 diststuff: $(DISTSTUFF)
-       cd doc; $(MAKE) $(MFLAGS) diststuff
+       cd doc; $(MAKE) $(MFLAGS) all-doc
 
 subdir_do: force
        @for i in $(DODIRS); do \
@@ -998,6 +998,8 @@ annotate.o: annotate.c $(defs_h) annotate.h $(value_h) target.h $(gdbtypes_h)
 
 arm-tdep.o: arm-tdep.c $(gdbcmd_h) $(gdbcore_h) $(inferior_h) $(defs_h)
 
+bcache.o: bcache.c bcache.h $(defs_h)
+
 blockframe.o: blockframe.c $(defs_h) $(gdbcore_h) $(inferior_h) \
        objfiles.h symfile.h target.h
 
index 813b60a..935c437 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,12 @@
 
 *** Changes since GDB-4.15:
 
+* Memory use reductions and statistics collection
+
+We have begun to implement changes that reduce gdb's memory requirements
+and to report statistics about memory usage.  Try the "maint print statistics"
+command, for example.
+
 * New native configurations
 
 Windows 95, Windows NT                         i[345]86-*-win32
diff --git a/gdb/bcache.c b/gdb/bcache.c
new file mode 100644 (file)
index 0000000..af80afb
--- /dev/null
@@ -0,0 +1,188 @@
+/* Implement a cached obstack.
+   Written by Fred Fish (fnf@cygnus.com)
+   Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bcache.h"
+
+/* FIXME:  Incredibly simplistic hash generator.  Probably way too expensive
+ (consider long strings) and unlikely to have good distribution across hash
+ values for typical input. */
+
+static unsigned int
+hash (bytes, count)
+     void *bytes;
+     int count;
+{
+  unsigned int len;
+  unsigned long hashval;
+  unsigned int c;
+  const unsigned char *data = bytes;
+
+  hashval = 0;
+  len = 0;
+  while (count-- > 0)
+    {
+      c = *data++;
+      hashval += c + (c << 17);
+      hashval ^= hashval >> 2;
+      ++len;
+    }
+  hashval += len + (len << 17);
+  hashval ^= hashval >> 2;
+  return (hashval % BCACHE_HASHSIZE);
+}
+
+static void *
+lookup_cache (bytes, count, hashval, bcachep)
+     void *bytes;
+     int count;
+     int hashval;
+     struct bcache *bcachep;
+{
+  void *location = NULL;
+  struct hashlink **hashtablep;
+  struct hashlink *linkp;
+
+  hashtablep = bcachep -> indextable[count];
+  if (hashtablep != NULL)
+    {
+      linkp = hashtablep[hashval];
+      while (linkp != NULL)
+       {
+         if (memcmp (linkp -> data, bytes, count) == 0)
+           {
+             location = linkp -> data;
+             break;
+           }
+         linkp = linkp -> next;
+       }
+    }
+  return (location);
+}
+
+void *
+bcache (bytes, count, bcachep)
+     void *bytes;
+     int count;
+     struct bcache *bcachep;
+{
+  int hashval;
+  void *location;
+  struct hashlink *newlink;
+  struct hashlink **linkpp;
+  struct hashlink ***hashtablepp;
+
+  if (count > BCACHE_MAXLENGTH)
+    {
+      /* Rare enough to just stash unique copies */
+      location = (void *) obstack_alloc (&bcachep->cache, count);
+      bcachep -> cache_bytes += count;
+      memcpy (location, bytes, count);
+      bcachep -> bcache_overflows++;
+    }
+  else
+    {
+      hashval = hash (bytes, count);
+      location = lookup_cache (bytes, count, hashval, bcachep);
+      if (location != NULL)
+       {
+         bcachep -> cache_savings += count;
+         bcachep -> cache_hits++;
+       }
+      else
+       {
+         bcachep -> cache_misses++;
+         hashtablepp = &bcachep -> indextable[count];
+         if (*hashtablepp == NULL)
+           {
+             *hashtablepp = (struct hashlink **)
+               obstack_alloc (&bcachep->cache, BCACHE_HASHSIZE * sizeof (struct hashlink *));
+             bcachep -> cache_bytes += sizeof (struct hashlink *);
+             memset (*hashtablepp, 0, BCACHE_HASHSIZE * sizeof (struct hashlink *));
+           }
+         linkpp = &(*hashtablepp)[hashval];
+         newlink = (struct hashlink *)
+           obstack_alloc (&bcachep->cache, sizeof (struct hashlink *) + count);
+         bcachep -> cache_bytes += sizeof (struct hashlink *) + count;
+         memcpy (newlink -> data, bytes, count);
+         newlink -> next = *linkpp;
+         *linkpp = newlink;
+         location = newlink -> data;
+       }
+    }
+  return (location);
+}
+
+#if MAINTENANCE_CMDS
+
+void
+print_bcache_statistics (bcachep, id)
+     struct bcache *bcachep;
+     char *id;
+{
+  struct hashlink **hashtablep;
+  struct hashlink *linkp;
+  int tidx, tcount, hidx, hcount, lcount, lmax, temp, lmaxt, lmaxh;
+
+  for (lmax = lcount = tcount = hcount = tidx = 0; tidx < BCACHE_MAXLENGTH; tidx++)
+    {
+      hashtablep = bcachep -> indextable[tidx];
+      if (hashtablep != NULL)
+       {
+         tcount++;
+         for (hidx = 0; hidx < BCACHE_HASHSIZE; hidx++)
+           {
+             linkp = hashtablep[hidx];
+             if (linkp != NULL)
+               {
+                 hcount++;
+                 for (temp = 0; linkp != NULL; linkp = linkp -> next)
+                   {
+                     lcount++;
+                     temp++;
+                   }
+                 if (temp > lmax)
+                   {
+                     lmax = temp;
+                     lmaxt = tidx;
+                     lmaxh = hidx;
+                   }
+               }
+           }
+       }
+    }
+  printf_filtered ("  Cached '%s' statistics:\n", id);
+  printf_filtered ("    Cache hits: %d\n", bcachep -> cache_hits);
+  printf_filtered ("    Cache misses: %d\n", bcachep -> cache_misses);
+  printf_filtered ("    Cache hit ratio: %d%%\n", ((bcachep -> cache_hits) * 100) /  (bcachep -> cache_hits + bcachep -> cache_misses));
+  printf_filtered ("    Space used for caching: %d\n", bcachep -> cache_bytes);
+  printf_filtered ("    Space saved by cache hits: %d\n", bcachep -> cache_savings);
+  printf_filtered ("    Number of bcache overflows: %d\n", bcachep -> bcache_overflows);
+  printf_filtered ("    Number of index buckets used: %d\n", tcount);
+  printf_filtered ("    Number of hash table buckets used: %d\n", hcount);
+  printf_filtered ("    Number of chained items: %d\n", lcount);
+  printf_filtered ("    Average hash table population: %d%%\n",
+                  (hcount * 100) / (tcount * BCACHE_HASHSIZE));
+  printf_filtered ("    Average chain length %d\n", lcount / hcount);
+  printf_filtered ("    Maximum chain length %d at %d:%d\n", lmax, lmaxt, lmaxh);
+}
+
+#endif /* MAINTENANCE_CMDS */
diff --git a/gdb/bcache.h b/gdb/bcache.h
new file mode 100644 (file)
index 0000000..e389c8e
--- /dev/null
@@ -0,0 +1,46 @@
+/* Include file cached obstack implementation.
+   Written by Fred Fish (fnf@cygnus.com)
+   Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef BCACHE_H
+#define BCACHE_H 1
+
+#define BCACHE_HASHLENGTH      12      /* Number of bits in hash value */
+#define BCACHE_HASHSIZE        (1 << BCACHE_HASHLENGTH)
+#define BCACHE_MAXLENGTH       128
+
+struct hashlink {
+  struct hashlink *next;
+  char data[1];
+};
+
+struct bcache {
+  struct obstack cache;
+  struct hashlink **indextable[BCACHE_MAXLENGTH];
+  int cache_hits;
+  int cache_misses;
+  int cache_bytes;
+  int cache_savings;
+  int bcache_overflows;
+};
+
+extern void *
+bcache PARAMS ((void *bytes, int count, struct bcache *bcachep));
+
+#endif /* BCACHE_H */
index c8fbec0..90a9ac9 100644 (file)
@@ -160,7 +160,7 @@ void hpread_symfile_finish PARAMS ((struct objfile *));
 
 static struct partial_symtab *hpread_start_psymtab
   PARAMS ((struct objfile *, struct section_offsets *, char *, CORE_ADDR, int,
-          struct partial_symbol *, struct partial_symbol *));
+          struct partial_symbol **, struct partial_symbol **));
 
 static struct partial_symtab *hpread_end_psymtab
   PARAMS ((struct partial_symtab *, char **, int, int, CORE_ADDR,
@@ -827,8 +827,8 @@ hpread_start_psymtab (objfile, section_offsets,
      char *filename;
      CORE_ADDR textlow;
      int ldsymoff;
-     struct partial_symbol *global_syms;
-     struct partial_symbol *static_syms;
+     struct partial_symbol **global_syms;
+     struct partial_symbol **static_syms;
 {
   struct partial_symtab *result =
   start_psymtab_common (objfile, section_offsets,
index 3b94eb9..5a0eca1 100644 (file)
@@ -249,7 +249,10 @@ maintenance_print_statistics (args, from_tty)
      char *args;
      int from_tty;
 {
+  int temp;
+
   print_objfile_statistics ();
+  print_symbol_bcache_statistics ();
 }
 
 /* The "maintenance print" command is defined as a prefix, with allow_unknown
index e486550..ed9f1cf 100644 (file)
@@ -159,6 +159,8 @@ allocate_objfile (abfd, mapped)
            objfile -> md = md;
            objfile -> mmfd = fd;
            /* Update pointers to functions to *our* copies */
+           obstack_chunkfun (&objfile -> psymbol_cache.cache, xmmalloc);
+           obstack_freefun (&objfile -> psymbol_cache.cache, mfree);
            obstack_chunkfun (&objfile -> psymbol_obstack, xmmalloc);
            obstack_freefun (&objfile -> psymbol_obstack, mfree);
            obstack_chunkfun (&objfile -> symbol_obstack, xmmalloc);
@@ -186,6 +188,9 @@ allocate_objfile (abfd, mapped)
            objfile -> mmfd = fd;
            objfile -> flags |= OBJF_MAPPED;
            mmalloc_setkey (objfile -> md, 0, objfile);
+           obstack_specify_allocation_with_arg (&objfile -> psymbol_cache.cache,
+                                                0, 0, xmmalloc, mfree,
+                                                objfile -> md);
            obstack_specify_allocation_with_arg (&objfile -> psymbol_obstack,
                                                 0, 0, xmmalloc, mfree,
                                                 objfile -> md);
@@ -228,6 +233,8 @@ allocate_objfile (abfd, mapped)
       objfile = (struct objfile *) xmalloc (sizeof (struct objfile));
       memset (objfile, 0, sizeof (struct objfile));
       objfile -> md = NULL;
+      obstack_specify_allocation (&objfile -> psymbol_cache.cache, 0, 0,
+                                 xmalloc, free);
       obstack_specify_allocation (&objfile -> psymbol_obstack, 0, 0, xmalloc,
                                  free);
       obstack_specify_allocation (&objfile -> symbol_obstack, 0, 0, xmalloc,
@@ -433,6 +440,7 @@ free_objfile (objfile)
       if (objfile->static_psymbols.list)
        mfree (objfile->md, objfile->static_psymbols.list);
       /* Free the obstacks for non-reusable objfiles */
+      obstack_free (&objfile -> psymbol_cache.cache, 0);
       obstack_free (&objfile -> psymbol_obstack, 0);
       obstack_free (&objfile -> symbol_obstack, 0);
       obstack_free (&objfile -> type_obstack, 0);
@@ -552,18 +560,18 @@ objfile_relocate (objfile, new_offsets)
   }
 
   {
-    struct partial_symbol *psym;
+    struct partial_symbol **psym;
 
     for (psym = objfile->global_psymbols.list;
         psym < objfile->global_psymbols.next;
         psym++)
-      if (SYMBOL_SECTION (psym) >= 0)
-       SYMBOL_VALUE_ADDRESS (psym) += ANOFFSET (delta, SYMBOL_SECTION (psym));
+      if (SYMBOL_SECTION (*psym) >= 0)
+       SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta, SYMBOL_SECTION (*psym));
     for (psym = objfile->static_psymbols.list;
         psym < objfile->static_psymbols.next;
         psym++)
-      if (SYMBOL_SECTION (psym) >= 0)
-       SYMBOL_VALUE_ADDRESS (psym) += ANOFFSET (delta, SYMBOL_SECTION (psym));
+      if (SYMBOL_SECTION (*psym) >= 0)
+       SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta, SYMBOL_SECTION (*psym));
   }
 
   {
index 0a8bbd3..f536056 100644 (file)
@@ -252,6 +252,11 @@ struct objfile
   struct obstack symbol_obstack;       /* Full symbols */
   struct obstack type_obstack;         /* Types */
 
+  /* A byte cache where we can stash arbitrary "chunks" of bytes that
+     will not change. */
+
+  struct bcache psymbol_cache;         /* Byte cache for partial syms */
+
   /* Vectors of all partial symbols read in from file.  The actual data
      is stored in the psymbol_obstack. */
 
index bcdf308..2de2922 100644 (file)
@@ -159,8 +159,8 @@ os9k_process_one_symbol PARAMS ((int, int, CORE_ADDR, char *,
 
 static struct partial_symtab *
 os9k_start_psymtab PARAMS ((struct objfile *, struct section_offsets *, char *,
-                       CORE_ADDR, int, int, struct partial_symbol *,
-                       struct partial_symbol *));
+                       CORE_ADDR, int, int, struct partial_symbol **,
+                       struct partial_symbol **));
 
 static struct partial_symtab *
 os9k_end_psymtab PARAMS ((struct partial_symtab *, char **, int, int, CORE_ADDR,
@@ -972,8 +972,8 @@ os9k_start_psymtab (objfile, section_offsets,
      CORE_ADDR textlow;
      int ldsymoff;
      int ldsymcnt;
-     struct partial_symbol *global_syms;
-     struct partial_symbol *static_syms;
+     struct partial_symbol **global_syms;
+     struct partial_symbol **static_syms;
 {
   struct partial_symtab *result =
       start_psymtab_common(objfile, section_offsets,
index dbdb943..b348738 100644 (file)
@@ -183,8 +183,8 @@ struct stab_section_list
 
 extern struct partial_symtab *
 start_psymtab PARAMS ((struct objfile *, struct section_offsets *, char *,
-                      CORE_ADDR, int, struct partial_symbol *,
-                      struct partial_symbol *));
+                      CORE_ADDR, int, struct partial_symbol **,
+                      struct partial_symbol **));
 
 extern struct partial_symtab *
 end_psymtab PARAMS ((struct partial_symtab *, char **, int, int, CORE_ADDR,
index 98b25df..8dc452a 100644 (file)
@@ -148,9 +148,9 @@ LOCAL FUNCTION
 
 DESCRIPTION
 
-       Given pointer to two partial symbol table entries, compare
-       them by name and return -N, 0, or +N (ala strcmp).  Typically
-       used by sorting routines like qsort().
+       Given pointers to pointers to two partial symbol table entries,
+       compare them by name and return -N, 0, or +N (ala strcmp).
+       Typically used by sorting routines like qsort().
 
 NOTES
 
@@ -167,8 +167,8 @@ compare_psymbols (s1p, s2p)
      const PTR s1p;
      const PTR s2p;
 {
-  register char *st1 = SYMBOL_NAME ((struct partial_symbol *) s1p);
-  register char *st2 = SYMBOL_NAME ((struct partial_symbol *) s2p);
+  register char *st1 = SYMBOL_NAME (*(struct partial_symbol **) s1p);
+  register char *st2 = SYMBOL_NAME (*(struct partial_symbol **) s2p);
 
   if ((st1[0] - st2[0]) || !st1[0])
     {
@@ -191,7 +191,7 @@ sort_pst_symbols (pst)
   /* Sort the global list; don't sort the static list */
 
   qsort (pst -> objfile -> global_psymbols.list + pst -> globals_offset,
-        pst -> n_global_syms, sizeof (struct partial_symbol),
+        pst -> n_global_syms, sizeof (struct partial_symbol *),
         compare_psymbols);
 }
 
@@ -1192,6 +1192,7 @@ reread_symbols ()
          objfile->static_psymbols.size = 0;
 
          /* Free the obstacks for non-reusable objfiles */
+         obstack_free (&objfile -> psymbol_cache.cache, 0);
          obstack_free (&objfile -> psymbol_obstack, 0);
          obstack_free (&objfile -> symbol_obstack, 0);
          obstack_free (&objfile -> type_obstack, 0);
@@ -1211,6 +1212,8 @@ reread_symbols ()
          objfile -> md = NULL;
          /* obstack_specify_allocation also initializes the obstack so
             it is empty.  */
+         obstack_specify_allocation (&objfile -> psymbol_cache.cache, 0, 0,
+                                     xmalloc, free);
          obstack_specify_allocation (&objfile -> psymbol_obstack, 0, 0,
                                      xmalloc, free);
          obstack_specify_allocation (&objfile -> symbol_obstack, 0, 0,
@@ -1616,8 +1619,8 @@ start_psymtab_common (objfile, section_offsets,
      struct section_offsets *section_offsets;
      char *filename;
      CORE_ADDR textlow;
-     struct partial_symbol *global_syms;
-     struct partial_symbol *static_syms;
+     struct partial_symbol **global_syms;
+     struct partial_symbol **static_syms;
 {
   struct partial_symtab *psymtab;
 
@@ -1651,24 +1654,29 @@ add_psymbol_to_list (name, namelength, namespace, class, list, val, language,
      struct objfile *objfile;
 {
   register struct partial_symbol *psym;
-  register char *demangled_name;
-
+  char *buf = alloca (namelength + 1);
+  struct partial_symbol psymbol;
+
+  /* Create local copy of the partial symbol */
+  memcpy (buf, name, namelength);
+  buf[namelength] = '\0';
+  SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache);
+  SYMBOL_VALUE (&psymbol) = val;
+  SYMBOL_SECTION (&psymbol) = 0;
+  SYMBOL_LANGUAGE (&psymbol) = language;
+  PSYMBOL_NAMESPACE (&psymbol) = namespace;
+  PSYMBOL_CLASS (&psymbol) = class;
+  SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language);
+
+  /* Stash the partial symbol away in the cache */
+  psym = bcache (&psymbol, sizeof (struct partial_symbol), &objfile->psymbol_cache);
+
+  /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
   if (list->next >= list->list + list->size)
     {
-      extend_psymbol_list (list,objfile);
+      extend_psymbol_list (list, objfile);
     }
-  psym = list->next++;
-  
-  SYMBOL_NAME (psym) =
-    (char *) obstack_alloc (&objfile->psymbol_obstack, namelength + 1);
-  memcpy (SYMBOL_NAME (psym), name, namelength);
-  SYMBOL_NAME (psym)[namelength] = '\0';
-  SYMBOL_VALUE (psym) = val;
-  SYMBOL_SECTION (psym) = 0;
-  SYMBOL_LANGUAGE (psym) = language;
-  PSYMBOL_NAMESPACE (psym) = namespace;
-  PSYMBOL_CLASS (psym) = class;
-  SYMBOL_INIT_LANGUAGE_SPECIFIC (psym, language);
+  *list->next++ = psym;
   OBJSTAT (objfile, n_psyms++);
 }
 
@@ -1687,24 +1695,29 @@ add_psymbol_addr_to_list (name, namelength, namespace, class, list, val,
      struct objfile *objfile;
 {
   register struct partial_symbol *psym;
-  register char *demangled_name;
-
+  char *buf = alloca (namelength + 1);
+  struct partial_symbol psymbol;
+
+  /* Create local copy of the partial symbol */
+  memcpy (buf, name, namelength);
+  buf[namelength] = '\0';
+  SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache);
+  SYMBOL_VALUE_ADDRESS (&psymbol) = val;
+  SYMBOL_SECTION (&psymbol) = 0;
+  SYMBOL_LANGUAGE (&psymbol) = language;
+  PSYMBOL_NAMESPACE (&psymbol) = namespace;
+  PSYMBOL_CLASS (&psymbol) = class;
+  SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language);
+
+  /* Stash the partial symbol away in the cache */
+  psym = bcache (&psymbol, sizeof (struct partial_symbol), &objfile->psymbol_cache);
+
+  /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
   if (list->next >= list->list + list->size)
     {
-      extend_psymbol_list (list,objfile);
+      extend_psymbol_list (list, objfile);
     }
-  psym = list->next++;
-  
-  SYMBOL_NAME (psym) =
-    (char *) obstack_alloc (&objfile->psymbol_obstack, namelength + 1);
-  memcpy (SYMBOL_NAME (psym), name, namelength);
-  SYMBOL_NAME (psym)[namelength] = '\0';
-  SYMBOL_VALUE_ADDRESS (psym) = val;
-  SYMBOL_SECTION (psym) = 0;
-  SYMBOL_LANGUAGE (psym) = language;
-  PSYMBOL_NAMESPACE (psym) = namespace;
-  PSYMBOL_CLASS (psym) = class;
-  SYMBOL_INIT_LANGUAGE_SPECIFIC (psym, language);
+  *list->next++ = psym;
   OBJSTAT (objfile, n_psyms++);
 }
 
@@ -1735,13 +1748,13 @@ init_psymbol_list (objfile, total_symbols)
   objfile -> global_psymbols.size = total_symbols / 10;
   objfile -> static_psymbols.size = total_symbols / 10;
   objfile -> global_psymbols.next =
-    objfile -> global_psymbols.list = (struct partial_symbol *)
+    objfile -> global_psymbols.list = (struct partial_symbol **)
       xmmalloc (objfile -> md, objfile -> global_psymbols.size
-                            * sizeof (struct partial_symbol));
+                            * sizeof (struct partial_symbol *));
   objfile -> static_psymbols.next =
-    objfile -> static_psymbols.list = (struct partial_symbol *)
+    objfile -> static_psymbols.list = (struct partial_symbol **)
       xmmalloc (objfile -> md, objfile -> static_psymbols.size
-                            * sizeof (struct partial_symbol));
+                            * sizeof (struct partial_symbol *));
 }
 \f
 void
index 6271a72..3c968f6 100644 (file)
@@ -23,10 +23,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* This file requires that you first include "bfd.h".  */
 
+/* Partial symbols are stored in the psymbol_cache and pointers to them
+   are kept in a dynamically grown array that is obtained from malloc and
+   grown as necessary via realloc.  Each objfile typically has two of these,
+   one for global symbols and one for static symbols.  Although this adds
+   a level of indirection for storing or accessing the partial symbols,
+   it allows us to throw away duplicate psymbols and set all pointers
+   to the single saved instance. */
+
 struct psymbol_allocation_list {
-  struct partial_symbol *list;
-  struct partial_symbol *next;
-  int size;
+  struct partial_symbol **list;        /* Pointer to first partial symbol pointer*/
+  struct partial_symbol **next;        /* Pointer to next avail storage for pointer */
+  int size;                    /* Number of symbols */
 };
 
 /* Structure to keep track of symbol reading functions for various
@@ -116,21 +124,22 @@ extend_psymbol_list PARAMS ((struct psymbol_allocation_list *,
 #define        ADD_PSYMBOL_VT_TO_LIST(NAME,NAMELENGTH,NAMESPACE,CLASS,LIST,VALUE,VT,LANGUAGE, OBJFILE) \
   do {                                                                 \
     register struct partial_symbol *psym;                              \
+    char *buf = alloca ((NAMELENGTH) + 1);                             \
+    struct partial_symbol psymbol;                                     \
+    memcpy (buf, (NAME), (NAMELENGTH));                                        \
+    buf[(NAMELENGTH)] = '\0';                                          \
+    SYMBOL_NAME (&psymbol) = bcache (buf, (NAMELENGTH) + 1, &(OBJFILE)->psymbol_cache); \
+    VT (&psymbol) = (VALUE);                                           \
+    SYMBOL_SECTION (&psymbol) = 0;                                     \
+    SYMBOL_LANGUAGE (&psymbol) = (LANGUAGE);                           \
+    PSYMBOL_NAMESPACE (&psymbol) = (NAMESPACE);                                \
+    PSYMBOL_CLASS (&psymbol) = (CLASS);                                        \
+    SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, (LANGUAGE));              \
+    psym = bcache (&psymbol, sizeof (struct partial_symbol), &(OBJFILE)->psymbol_cache); \
     if ((LIST).next >= (LIST).list + (LIST).size)                      \
-      extend_psymbol_list (&(LIST),(OBJFILE));                         \
-    psym = (LIST).next++;                                              \
-    SYMBOL_NAME (psym) =                                               \
-      (char *) obstack_alloc (&objfile->psymbol_obstack,               \
-                             (NAMELENGTH) + 1);                        \
-    memcpy (SYMBOL_NAME (psym), (NAME), (NAMELENGTH));                 \
-    SYMBOL_NAME (psym)[(NAMELENGTH)] = '\0';                           \
-    SYMBOL_NAMESPACE (psym) = (NAMESPACE);                             \
-    SYMBOL_SECTION (psym) = 0;                                         \
-    PSYMBOL_CLASS (psym) = (CLASS);                                    \
-    VT (psym) = (VALUE);                                               \
-    SYMBOL_LANGUAGE (psym) = (LANGUAGE);                               \
-    SYMBOL_INIT_LANGUAGE_SPECIFIC (psym, LANGUAGE);                    \
-    OBJSTAT (objfile, n_psyms++);                                      \
+      extend_psymbol_list (&(LIST), (OBJFILE));                                \
+    *(LIST).next++ = psym;                                             \
+    OBJSTAT ((OBJFILE), n_psyms++);                                    \
   } while (0)
 
 /* Add a symbol with an integer value to a psymtab. */
@@ -174,8 +183,8 @@ new_symfile_objfile PARAMS ((struct objfile *, int, int));
 extern struct partial_symtab *
 start_psymtab_common PARAMS ((struct objfile *, struct section_offsets *,
                              char *, CORE_ADDR,
-                             struct partial_symbol *,
-                             struct partial_symbol *));
+                             struct partial_symbol **,
+                             struct partial_symbol **));
 
 /* Sorting your symbols for fast lookup or alphabetical printing.  */
 
index d4b3d68..8485c59 100644 (file)
@@ -63,7 +63,7 @@ static int
 block_depth PARAMS ((struct block *));
 
 static void
-print_partial_symbol PARAMS ((struct partial_symbol *, int, char *, GDB_FILE *));
+print_partial_symbols PARAMS ((struct partial_symbol **, int, char *, GDB_FILE *));
 
 struct print_symbol_args {
   struct symbol *symbol;
@@ -153,6 +153,20 @@ free_symtab (s)
 #if MAINTENANCE_CMDS
 
 void
+print_symbol_bcache_statistics ()
+{
+  struct objfile *objfile;
+
+  immediate_quit++;
+  ALL_OBJFILES (objfile)
+    {
+      printf_filtered ("Cached obstack statistics for '%s':\n", objfile -> name);
+      print_bcache_statistics (&objfile -> psymbol_cache, "partial symbol obstack");
+    }
+  immediate_quit--;
+}
+
+void
 print_objfile_statistics ()
 {
   struct objfile *objfile;
@@ -373,13 +387,13 @@ dump_psymtab (objfile, psymtab, outfile)
     }
   if (psymtab -> n_global_syms > 0)
     {
-      print_partial_symbol (objfile -> global_psymbols.list
+      print_partial_symbols (objfile -> global_psymbols.list
                            + psymtab -> globals_offset,
                            psymtab -> n_global_syms, "Global", outfile);
     }
   if (psymtab -> n_static_syms > 0)
     {
-      print_partial_symbol (objfile -> static_psymbols.list
+      print_partial_symbols (objfile -> static_psymbols.list
                            + psymtab -> statics_offset,
                            psymtab -> n_static_syms, "Static", outfile);
     }
@@ -461,7 +475,7 @@ dump_symtab (objfile, symtab, outfile)
          s.depth = depth + 1;
          s.outfile = outfile;
          catch_errors (print_symbol, &s, "Error printing symbol:\n",
-                       RETURN_MASK_ERROR);
+                       RETURN_MASK_ALL);
        }
     }
   fprintf_filtered (outfile, "\n");
@@ -730,23 +744,22 @@ maintenance_print_psymbols (args, from_tty)
 }
 
 static void
-print_partial_symbol (p, count, what, outfile)
-     struct partial_symbol *p;
+print_partial_symbols (p, count, what, outfile)
+     struct partial_symbol **p;
      int count;
      char *what;
      GDB_FILE *outfile;
 {
-
   fprintf_filtered (outfile, "  %s partial symbols:\n", what);
   while (count-- > 0)
     {
-      fprintf_filtered (outfile, "    `%s'", SYMBOL_NAME(p));
-      if (SYMBOL_DEMANGLED_NAME (p) != NULL)
+      fprintf_filtered (outfile, "    `%s'", SYMBOL_NAME(*p));
+      if (SYMBOL_DEMANGLED_NAME (*p) != NULL)
        {
-         fprintf_filtered (outfile, "  `%s'", SYMBOL_DEMANGLED_NAME (p));
+         fprintf_filtered (outfile, "  `%s'", SYMBOL_DEMANGLED_NAME (*p));
        }
       fputs_filtered (", ", outfile);
-      switch (SYMBOL_NAMESPACE (p))
+      switch (SYMBOL_NAMESPACE (*p))
        {
        case UNDEF_NAMESPACE:
          fputs_filtered ("undefined namespace, ", outfile);
@@ -764,7 +777,7 @@ print_partial_symbol (p, count, what, outfile)
          fputs_filtered ("<invalid namespace>, ", outfile);
          break;
        }
-      switch (SYMBOL_CLASS (p))
+      switch (SYMBOL_CLASS (*p))
        {
        case LOC_UNDEF:
          fputs_filtered ("undefined", outfile);
@@ -822,7 +835,7 @@ print_partial_symbol (p, count, what, outfile)
       /* FIXME-32x64: Need to use SYMBOL_VALUE_ADDRESS, etc.; this
         could be 32 bits when some of the other fields in the union
         are 64.  */
-      fprintf_filtered (outfile, "0x%lx\n", SYMBOL_VALUE (p));
+      fprintf_filtered (outfile, "0x%lx\n", SYMBOL_VALUE (*p));
       p++;
     }
 }
@@ -901,7 +914,7 @@ maintenance_check_symtabs (ignore, from_tty)
      int from_tty;
 {
   register struct symbol *sym;
-  register struct partial_symbol *psym;
+  register struct partial_symbol **psym;
   register struct symtab *s = NULL;
   register struct partial_symtab *ps;
   struct blockvector *bv;
@@ -920,12 +933,12 @@ maintenance_check_symtabs (ignore, from_tty)
       length = ps->n_static_syms;
       while (length--)
        {
-         sym = lookup_block_symbol (b, SYMBOL_NAME (psym),
-                                    SYMBOL_NAMESPACE (psym));
+         sym = lookup_block_symbol (b, SYMBOL_NAME (*psym),
+                                    SYMBOL_NAMESPACE (*psym));
          if (!sym)
            {
              printf_filtered ("Static symbol `");
-             puts_filtered (SYMBOL_NAME (psym));
+             puts_filtered (SYMBOL_NAME (*psym));
              printf_filtered ("' only found in ");
              puts_filtered (ps->filename);
              printf_filtered (" psymtab\n");
@@ -937,12 +950,12 @@ maintenance_check_symtabs (ignore, from_tty)
       length = ps->n_global_syms;
       while (length--)
        {
-         sym = lookup_block_symbol (b, SYMBOL_NAME (psym),
-                                    SYMBOL_NAMESPACE (psym));
+         sym = lookup_block_symbol (b, SYMBOL_NAME (*psym),
+                                    SYMBOL_NAMESPACE (*psym));
          if (!sym)
            {
              printf_filtered ("Global symbol `");
-             puts_filtered (SYMBOL_NAME (psym));
+             puts_filtered (SYMBOL_NAME (*psym));
              printf_filtered ("' only found in ");
              puts_filtered (ps->filename);
              printf_filtered (" psymtab\n");
@@ -998,7 +1011,7 @@ block_depth (block)
 
 \f
 /* Increase the space allocated for LISTP, which is probably
-   global_psymbol_list or static_psymbol_list. This space will eventually
+   global_psymbols or static_psymbols. This space will eventually
    be freed in free_objfile().  */
 
 void
@@ -1010,15 +1023,15 @@ extend_psymbol_list (listp, objfile)
   if (listp->size == 0)
     {
       new_size = 255;
-      listp->list = (struct partial_symbol *)
-       xmmalloc (objfile -> md, new_size * sizeof (struct partial_symbol));
+      listp->list = (struct partial_symbol **)
+       xmmalloc (objfile -> md, new_size * sizeof (struct partial_symbol *));
     }
   else
     {
       new_size = listp->size * 2;
-      listp->list = (struct partial_symbol *)
+      listp->list = (struct partial_symbol **)
        xmrealloc (objfile -> md, (char *) listp->list,
-                  new_size * sizeof (struct partial_symbol));
+                  new_size * sizeof (struct partial_symbol *));
     }
   /* Next assumes we only went one over.  Should be good if
      program works correctly */
index 49b0c1a..c7703dd 100644 (file)
@@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "obstack.h"
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
+#include "bcache.h"
 
 /* Don't do this; it means that if some .o's are compiled with GNU C
    and some are not (easy to do accidentally the way we configure
index b553102..7704a5f 100644 (file)
@@ -1933,7 +1933,7 @@ static unsigned int first_fun_line_offset;
 
 static struct partial_symtab *xcoff_start_psymtab
   PARAMS ((struct objfile *, struct section_offsets *, char *, int,
-          struct partial_symbol *, struct partial_symbol *));
+          struct partial_symbol **, struct partial_symbol **));
 
 /* Allocate and partially fill a partial symtab.  It will be
    completely filled at the end of the symbol list.
@@ -1949,8 +1949,8 @@ xcoff_start_psymtab (objfile, section_offsets,
      struct section_offsets *section_offsets;
      char *filename;
      int first_symnum;
-     struct partial_symbol *global_syms;
-     struct partial_symbol *static_syms;
+     struct partial_symbol **global_syms;
+     struct partial_symbol **static_syms;
 {
   struct partial_symtab *result =
     start_psymtab_common (objfile, section_offsets,