* 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 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.
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.
# 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)
# 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 \
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)
# 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 \
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 \
rm -f Makefile
diststuff: $(DISTSTUFF)
- cd doc; $(MAKE) $(MFLAGS) diststuff
+ cd doc; $(MAKE) $(MFLAGS) all-doc
subdir_do: force
@for i in $(DODIRS); do \
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
*** 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
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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 */
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,
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,
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
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);
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);
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,
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);
}
{
- 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));
}
{
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. */
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,
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,
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,
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
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])
{
/* 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);
}
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);
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,
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;
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++);
}
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++);
}
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
/* 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
#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. */
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. */
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;
#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 ()
{
}
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);
}
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");
}
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);
fputs_filtered ("<invalid namespace>, ", outfile);
break;
}
- switch (SYMBOL_CLASS (p))
+ switch (SYMBOL_CLASS (*p))
{
case LOC_UNDEF:
fputs_filtered ("undefined", 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++;
}
}
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;
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");
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");
\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
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 */
#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
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.
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,