From 2ad5709f00b91860c204e1556eb917d42984d40d Mon Sep 17 00:00:00 2001 From: Fred Fish Date: Fri, 16 Feb 1996 22:14:47 +0000 Subject: [PATCH] * 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 **". --- gdb/ChangeLog | 49 +++++++++++++ gdb/Makefile.in | 26 +++---- gdb/NEWS | 6 ++ gdb/bcache.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++ gdb/bcache.h | 46 ++++++++++++ gdb/hpread.c | 6 +- gdb/maint.c | 3 + gdb/objfiles.c | 18 +++-- gdb/objfiles.h | 5 ++ gdb/os9kread.c | 8 +-- gdb/stabsread.h | 4 +- gdb/symfile.c | 97 ++++++++++++++----------- gdb/symfile.h | 47 +++++++----- gdb/symmisc.c | 63 +++++++++------- gdb/symtab.h | 1 + gdb/xcoffread.c | 6 +- 16 files changed, 458 insertions(+), 115 deletions(-) create mode 100644 gdb/bcache.c create mode 100644 gdb/bcache.h diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b2f631d7b8..1310795469 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,52 @@ +Fri Feb 16 14:00:54 1996 Fred Fish + + * 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 * dwarfread.c (free_utypes): New function. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 51d8e3843f..e1167cba0f 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -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 diff --git a/gdb/NEWS b/gdb/NEWS index 813b60aafb..935c437d0d 100644 --- 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 index 0000000000..af80afbbdd --- /dev/null +++ b/gdb/bcache.c @@ -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 index 0000000000..e389c8eb16 --- /dev/null +++ b/gdb/bcache.h @@ -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 */ diff --git a/gdb/hpread.c b/gdb/hpread.c index c8fbec072c..90a9ac9591 100644 --- a/gdb/hpread.c +++ b/gdb/hpread.c @@ -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, diff --git a/gdb/maint.c b/gdb/maint.c index 3b94eb90a3..5a0eca11f5 100644 --- a/gdb/maint.c +++ b/gdb/maint.c @@ -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 diff --git a/gdb/objfiles.c b/gdb/objfiles.c index e48655016f..ed9f1cf3ae 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -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)); } { diff --git a/gdb/objfiles.h b/gdb/objfiles.h index 0a8bbd3803..f53605609a 100644 --- a/gdb/objfiles.h +++ b/gdb/objfiles.h @@ -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. */ diff --git a/gdb/os9kread.c b/gdb/os9kread.c index bcdf30834d..2de292219b 100644 --- a/gdb/os9kread.c +++ b/gdb/os9kread.c @@ -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, diff --git a/gdb/stabsread.h b/gdb/stabsread.h index dbdb94395a..b348738fc0 100644 --- a/gdb/stabsread.h +++ b/gdb/stabsread.h @@ -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, diff --git a/gdb/symfile.c b/gdb/symfile.c index 98b25df5d3..8dc452ae60 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -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 *)); } void diff --git a/gdb/symfile.h b/gdb/symfile.h index 6271a72969..3c968f64ba 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -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. */ diff --git a/gdb/symmisc.c b/gdb/symmisc.c index d4b3d688f2..8485c596bd 100644 --- a/gdb/symmisc.c +++ b/gdb/symmisc.c @@ -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; @@ -152,6 +152,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 () { @@ -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 (", ", 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) /* 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 */ diff --git a/gdb/symtab.h b/gdb/symtab.h index 49b0c1aa86..c7703dd7fd 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -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 diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c index b5531024da..7704a5fba4 100644 --- a/gdb/xcoffread.c +++ b/gdb/xcoffread.c @@ -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, -- 2.34.1