Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* RFC: save lots of memory
@ 2009-11-05  1:24 Tom Tromey
  2009-11-05 17:28 ` Joel Brobecker
  2009-11-05 19:59 ` Daniel Jacobowitz
  0 siblings, 2 replies; 9+ messages in thread
From: Tom Tromey @ 2009-11-05  1:24 UTC (permalink / raw)
  To: gdb-patches

While running massif on gdb I found that, to my surprise,
symbol_set_names is a large space user.  This is surprising because
there is no reason to copy symbol names, at least for DWARF -- they are
guaranteed to hang around until the objfile is destroyed.

This patch changes gdb so that such names are not copied.  This saves a
lot of memory.  For example, I ran OO.o writer and attached to it with
gdb (I have full debug info installed for OO.o and all its
dependencies).

Peak memory before: 219580200
Peak memory after : 198568560
Savings           :  21011640

That is, we save about 10% of the heap.

I changed the contents of the demangled name hash; the new approach
saves memory if you assume that most mangled names do not need to be
copied and that names are on average longer than the width of a pointer.

I only updated the ELF and DWARF readers.  I don't know enough about the
other readers to attempt those.  As it stands, this patch will make
those use more memory.  I think this is ok, but if it is a problem
either someone could fix the other readers, or we could have two
demangled hashes.

The signal to symbol_set_names that a name does not need to be copied is
passing -1 for the name length.  I don't consider that to be too gross,
but I realize others may disagree.

We might be able to save a bit more memory using this same technique, by
not copying the filename argument to allocate_psymtab.  According to
massif this accounts for 5791200 bytes in my test run -- but I don't
know how many of those do not need to be copied.  Putting the file names
into the bcache might also help.

Let me know what you think.

Tom

2009-11-04  Tom Tromey  <tromey@redhat.com>

	* symtab.h (prim_record_minimal_symbol_full): Declare.
	* symtab.c (struct demangled_name_entry): New struct.
	(hash_demangled_name_entry): New function.
	(eq_demangled_name_entry): Likewise.
	(create_demangled_names_hash): Use new functions.
	(symbol_set_names): Allow len==-1.  Use struct
	demangled_name_entry.
	* minsyms.c (prim_record_minimal_symbol_full): New function.
	(prim_record_minimal_symbol_and_info): Use it.
	* elfread.c (record_minimal_symbol): Add name_len argument.  Call
	prim_record_minimal_symbol_full.
	(elf_symtab_read): Add copy_names argument.  Pass -1 to
	record_minimal_symbol when appropriate.
	(elf_symfile_read): Update calls to elf_symtab_read.
	* dwarf2read.c (add_partial_symbol): Pass -1 to
	add_psymbol_to_list when appropriate.
	(load_partial_dies): Likewise.
	(new_symbol): Pass -1 to SYMBOL_SET_NAMES.
	* cp-namespace.c (check_one_possible_namespace_symbol): Don't save
	name on the obstack.  Pass TYPE_NAME and length of -1 to
	SYMBOL_SET_NAMES.

diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index d2d8f2e..0a3892d 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -714,7 +714,6 @@ check_one_possible_namespace_symbol (const char *name, int len,
   if (sym == NULL)
     {
       struct type *type;
-      name_copy = obsavestring (name, len, &objfile->objfile_obstack);
 
       type = init_type (TYPE_CODE_NAMESPACE, 0, 0, name_copy, objfile);
 
@@ -723,7 +722,9 @@ check_one_possible_namespace_symbol (const char *name, int len,
       sym = obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol));
       memset (sym, 0, sizeof (struct symbol));
       SYMBOL_LANGUAGE (sym) = language_cplus;
-      SYMBOL_SET_NAMES (sym, name_copy, len, objfile);
+      /* Note that init_type copied the name to the objfile's
+	 obstack.  */
+      SYMBOL_SET_NAMES (sym, TYPE_NAME (type), -1, objfile);
       SYMBOL_CLASS (sym) = LOC_TYPEDEF;
       SYMBOL_TYPE (sym) = type;
       SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 9bf89d7..3a80529 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -2391,7 +2391,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
   const char *my_prefix;
   const struct partial_symbol *psym = NULL;
   CORE_ADDR baseaddr;
-  int built_actual_name = 0;
+  int built_actual_name = 0, actual_name_len;
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
@@ -2405,6 +2405,8 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
   if (actual_name == NULL)
     actual_name = pdi->name;
 
+  actual_name_len = built_actual_name ? strlen (actual_name) : -1;
+
   switch (pdi->tag)
     {
     case DW_TAG_subprogram:
@@ -2416,7 +2418,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
              in the global scope.  */
 	  /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
 	     mst_text, objfile); */
-	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+	  psym = add_psymbol_to_list (actual_name, actual_name_len,
 				      VAR_DOMAIN, LOC_BLOCK,
 				      &objfile->global_psymbols,
 				      0, pdi->lowpc + baseaddr,
@@ -2426,7 +2428,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 	{
 	  /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
 	     mst_file_text, objfile); */
-	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+	  psym = add_psymbol_to_list (actual_name, actual_name_len,
 				      VAR_DOMAIN, LOC_BLOCK,
 				      &objfile->static_psymbols,
 				      0, pdi->lowpc + baseaddr,
@@ -2452,7 +2454,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 	  if (pdi->locdesc)
 	    addr = decode_locdesc (pdi->locdesc, cu);
 	  if (pdi->locdesc || pdi->has_type)
-	    psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+	    psym = add_psymbol_to_list (actual_name, actual_name_len,
 					VAR_DOMAIN, LOC_STATIC,
 					&objfile->global_psymbols,
 					0, addr + baseaddr,
@@ -2470,7 +2472,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 	  addr = decode_locdesc (pdi->locdesc, cu);
 	  /*prim_record_minimal_symbol (actual_name, addr + baseaddr,
 	     mst_file_data, objfile); */
-	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+	  psym = add_psymbol_to_list (actual_name, actual_name_len,
 				      VAR_DOMAIN, LOC_STATIC,
 				      &objfile->static_psymbols,
 				      0, addr + baseaddr,
@@ -2480,13 +2482,13 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
     case DW_TAG_typedef:
     case DW_TAG_base_type:
     case DW_TAG_subrange_type:
-      add_psymbol_to_list (actual_name, strlen (actual_name),
+      add_psymbol_to_list (actual_name, actual_name_len,
 			   VAR_DOMAIN, LOC_TYPEDEF,
 			   &objfile->static_psymbols,
 			   0, (CORE_ADDR) 0, cu->language, objfile);
       break;
     case DW_TAG_namespace:
-      add_psymbol_to_list (actual_name, strlen (actual_name),
+      add_psymbol_to_list (actual_name, actual_name_len,
 			   VAR_DOMAIN, LOC_TYPEDEF,
 			   &objfile->global_psymbols,
 			   0, (CORE_ADDR) 0, cu->language, objfile);
@@ -2510,7 +2512,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 
       /* NOTE: carlton/2003-10-07: See comment in new_symbol about
 	 static vs. global.  */
-      add_psymbol_to_list (actual_name, strlen (actual_name),
+      add_psymbol_to_list (actual_name, actual_name_len,
 			   STRUCT_DOMAIN, LOC_TYPEDEF,
 			   (cu->language == language_cplus
 			    || cu->language == language_java)
@@ -2520,7 +2522,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 
       break;
     case DW_TAG_enumerator:
-      add_psymbol_to_list (actual_name, strlen (actual_name),
+      add_psymbol_to_list (actual_name, actual_name_len,
 			   VAR_DOMAIN, LOC_CONST,
 			   (cu->language == language_cplus
 			    || cu->language == language_java)
@@ -6503,7 +6505,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
 	      || part_die->tag == DW_TAG_subrange_type))
 	{
 	  if (building_psymtab && part_die->name != NULL)
-	    add_psymbol_to_list (part_die->name, strlen (part_die->name),
+	    add_psymbol_to_list (part_die->name, -1,
 				 VAR_DOMAIN, LOC_TYPEDEF,
 				 &cu->objfile->static_psymbols,
 				 0, (CORE_ADDR) 0, cu->language, cu->objfile);
@@ -6524,7 +6526,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
 	  if (part_die->name == NULL)
 	    complaint (&symfile_complaints, _("malformed enumerator DIE ignored"));
 	  else if (building_psymtab)
-	    add_psymbol_to_list (part_die->name, strlen (part_die->name),
+	    add_psymbol_to_list (part_die->name, -1,
 				 VAR_DOMAIN, LOC_CONST,
 				 (cu->language == language_cplus
 				  || cu->language == language_java)
@@ -8304,7 +8306,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 
       /* Cache this symbol's name and the name's demangled form (if any).  */
       SYMBOL_LANGUAGE (sym) = cu->language;
-      SYMBOL_SET_NAMES (sym, name, strlen (name), objfile);
+      SYMBOL_SET_NAMES (sym, name, -1, objfile);
 
       /* Default assumptions.
          Use the passed type or decode it from the die.  */
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 131d7d2..ef45410 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -172,7 +172,7 @@ elf_locate_sections (bfd *ignore_abfd, asection *sectp, void *eip)
 }
 
 static struct minimal_symbol *
-record_minimal_symbol (char *name, CORE_ADDR address,
+record_minimal_symbol (const char *name, int name_len, CORE_ADDR address,
 		       enum minimal_symbol_type ms_type,
 		       asection *bfd_section, struct objfile *objfile)
 {
@@ -181,8 +181,9 @@ record_minimal_symbol (char *name, CORE_ADDR address,
   if (ms_type == mst_text || ms_type == mst_file_text)
     address = gdbarch_smash_text_address (gdbarch, address);
 
-  return prim_record_minimal_symbol_and_info
-    (name, address, ms_type, bfd_section->index, bfd_section, objfile);
+  return prim_record_minimal_symbol_full (name, name_len, address,
+					  ms_type, bfd_section->index,
+					  bfd_section, objfile);
 }
 
 /*
@@ -216,7 +217,8 @@ record_minimal_symbol (char *name, CORE_ADDR address,
 
 static void
 elf_symtab_read (struct objfile *objfile, int type,
-		 long number_of_symbols, asymbol **symbol_table)
+		 long number_of_symbols, asymbol **symbol_table,
+		 int copy_names)
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   long storage_needed;
@@ -297,7 +299,8 @@ elf_symtab_read (struct objfile *objfile, int type,
 	  symaddr += ANOFFSET (objfile->section_offsets, sect->index);
 
 	  msym = record_minimal_symbol
-	    ((char *) sym->name, symaddr, mst_solib_trampoline, sect, objfile);
+	    (sym->name, copy_names ? strlen (sym->name) : -1,
+	     symaddr, mst_solib_trampoline, sect, objfile);
 	  if (msym != NULL)
 	    msym->filename = filesymname;
 	  continue;
@@ -510,7 +513,7 @@ elf_symtab_read (struct objfile *objfile, int type,
 	      continue;	/* Skip this symbol. */
 	    }
 	  msym = record_minimal_symbol
-	    ((char *) sym->name, symaddr,
+	    (sym->name, copy_names ? strlen (sym->name) : -1, symaddr,
 	     ms_type, sym->section, objfile);
 
 	  if (msym)
@@ -545,15 +548,11 @@ elf_symtab_read (struct objfile *objfile, int type,
 
 	      if (len > 4 && strcmp (sym->name + len - 4, "@plt") == 0)
 		{
-		  char *base_name = xmalloc (len - 4 + 1);
 		  struct minimal_symbol *mtramp;
 
-		  memcpy (base_name, sym->name, len - 4);
-		  base_name[len - 4] = '\0';
-		  mtramp = record_minimal_symbol (base_name, symaddr,
+		  mtramp = record_minimal_symbol (sym->name, len - 4, symaddr,
 						  mst_solib_trampoline,
 						  sym->section, objfile);
-		  xfree (base_name);
 		  if (mtramp)
 		    {
 		      MSYMBOL_SIZE (mtramp) = MSYMBOL_SIZE (msym);
@@ -638,7 +637,7 @@ elf_symfile_read (struct objfile *objfile, int mainline)
 	error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd),
 	       bfd_errmsg (bfd_get_error ()));
 
-      elf_symtab_read (objfile, ST_REGULAR, symcount, symbol_table);
+      elf_symtab_read (objfile, ST_REGULAR, symcount, symbol_table, 0);
     }
 
   /* Add the dynamic symbols.  */
@@ -656,7 +655,7 @@ elf_symfile_read (struct objfile *objfile, int mainline)
 	error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd),
 	       bfd_errmsg (bfd_get_error ()));
 
-      elf_symtab_read (objfile, ST_DYNAMIC, dynsymcount, dyn_symbol_table);
+      elf_symtab_read (objfile, ST_DYNAMIC, dynsymcount, dyn_symbol_table, 0);
     }
 
   /* Add synthetic symbols - for instance, names for any PLT entries.  */
@@ -674,7 +673,7 @@ elf_symfile_read (struct objfile *objfile, int mainline)
       for (i = 0; i < synthcount; i++)
 	synth_symbol_table[i] = synthsyms + i;
       make_cleanup (xfree, synth_symbol_table);
-      elf_symtab_read (objfile, ST_SYNTHETIC, synthcount, synth_symbol_table);
+      elf_symtab_read (objfile, ST_SYNTHETIC, synthcount, synth_symbol_table, 1);
     }
 
   /* Install any minimal symbols that have been collected as the current
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index 64d20d2..39ed3bf 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -757,11 +757,12 @@ prim_record_minimal_symbol (const char *name, CORE_ADDR address,
    newly created.  */
 
 struct minimal_symbol *
-prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
-				     enum minimal_symbol_type ms_type,
-				     int section,
-				     asection *bfd_section,
-				     struct objfile *objfile)
+prim_record_minimal_symbol_full (const char *name, int name_len,
+				 CORE_ADDR address,
+				 enum minimal_symbol_type ms_type,
+				 int section,
+				 asection *bfd_section,
+				 struct objfile *objfile)
 {
   struct obj_section *obj_section;
   struct msym_bunch *new;
@@ -780,7 +781,11 @@ prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
   /* It's safe to strip the leading char here once, since the name
      is also stored stripped in the minimal symbol table. */
   if (name[0] == get_symbol_leading_char (objfile->obfd))
-    ++name;
+    {
+      ++name;
+      if (name_len != -1)
+	--name_len;
+    }
 
   if (ms_type == mst_file_text && strncmp (name, "__gnu_compiled", 14) == 0)
     return (NULL);
@@ -795,7 +800,7 @@ prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
   msymbol = &msym_bunch->contents[msym_bunch_index];
   SYMBOL_INIT_LANGUAGE_SPECIFIC (msymbol, language_unknown);
   SYMBOL_LANGUAGE (msymbol) = language_auto;
-  SYMBOL_SET_NAMES (msymbol, (char *)name, strlen (name), objfile);
+  SYMBOL_SET_NAMES (msymbol, name, name_len, objfile);
 
   SYMBOL_VALUE_ADDRESS (msymbol) = address;
   SYMBOL_SECTION (msymbol) = section;
@@ -828,6 +833,21 @@ prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
   return msymbol;
 }
 
+/* Record a minimal symbol in the msym bunches.  Returns the symbol
+   newly created.  */
+
+struct minimal_symbol *
+prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
+				     enum minimal_symbol_type ms_type,
+				     int section,
+				     asection *bfd_section,
+				     struct objfile *objfile)
+{
+  return prim_record_minimal_symbol_full (name, strlen (name),
+					  address, ms_type, section,
+					  bfd_section, objfile);
+}
+
 /* Compare two minimal symbols by address and return a signed result based
    on unsigned comparisons, so that we sort into unsigned numeric order.  
    Within groups with the same address, sort by name.  */
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 03586c3..211862e 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -427,6 +427,30 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
 
 /* Functions to initialize a symbol's mangled name.  */
 
+/* Objects of this type are stored in the demangled name hash table.  */
+struct demangled_name_entry
+{
+  char *mangled;
+  char demangled[1];
+};
+
+/* Hash function for the demangled name hash.  */
+static hashval_t
+hash_demangled_name_entry (const void *data)
+{
+  const struct demangled_name_entry *e = data;
+  return htab_hash_string (e->mangled);
+}
+
+/* Equality function for the demangled name hash.  */
+static int
+eq_demangled_name_entry (const void *a, const void *b)
+{
+  const struct demangled_name_entry *da = a;
+  const struct demangled_name_entry *db = b;
+  return strcmp (da->mangled, db->mangled) == 0;
+}
+
 /* Create the hash table used for demangled names.  Each hash entry is
    a pair of strings; one for the mangled name and one for the demangled
    name.  The entry is hashed via just the mangled name.  */
@@ -440,7 +464,7 @@ create_demangled_names_hash (struct objfile *objfile)
      1% in symbol reading.  */
 
   objfile->demangled_names_hash = htab_create_alloc
-    (256, htab_hash_string, (int (*) (const void *, const void *)) streq,
+    (256, hash_demangled_name_entry, eq_demangled_name_entry,
      NULL, xcalloc, xfree);
 }
 
@@ -496,10 +520,14 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 }
 
 /* Set both the mangled and demangled (if any) names for GSYMBOL based
-   on LINKAGE_NAME and LEN.  The hash table corresponding to OBJFILE
-   is used, and the memory comes from that objfile's objfile_obstack.
-   LINKAGE_NAME is copied, so the pointer can be discarded after
-   calling this function.  */
+   on LINKAGE_NAME and LEN.  Ordinarily, NAME is copied onto the
+   objfile's obstack; but if LEN is -1 then this function assumes that
+   NAME is both NUL-terminated and correctly saved (either permanently
+   or with a lifetime tied to the objfile), and it will not be copied.
+   
+   The hash table corresponding to OBJFILE is used, and the memory
+   comes from that objfile's objfile_obstack.  LINKAGE_NAME is copied,
+   so the pointer can be discarded after calling this function.  */
 
 /* We have to be careful when dealing with Java names: when we run
    into a Java minimal symbol, we don't know it's a Java symbol, so it
@@ -524,7 +552,7 @@ void
 symbol_set_names (struct general_symbol_info *gsymbol,
 		  const char *linkage_name, int len, struct objfile *objfile)
 {
-  char **slot;
+  struct demangled_name_entry **slot;
   /* A 0-terminated copy of the linkage name.  */
   const char *linkage_name_copy;
   /* A copy of the linkage name that might have a special Java prefix
@@ -532,9 +560,11 @@ symbol_set_names (struct general_symbol_info *gsymbol,
   const char *lookup_name;
   /* The length of lookup_name.  */
   int lookup_len;
+  int original_len = len;
+  struct demangled_name_entry entry;
 
-  if (objfile->demangled_names_hash == NULL)
-    create_demangled_names_hash (objfile);
+  if (len == -1)
+    len = strlen (linkage_name);
 
   if (gsymbol->language == language_ada)
     {
@@ -546,14 +576,22 @@ symbol_set_names (struct general_symbol_info *gsymbol,
          been observed with Java.  Because we don't store the demangled
          name with the symbol, we don't need to use the same trick
          as Java.  */
-      gsymbol->name = obstack_alloc (&objfile->objfile_obstack, len + 1);
-      memcpy (gsymbol->name, linkage_name, len);
-      gsymbol->name[len] = '\0';
+      if (original_len == -1)
+	gsymbol->name = (char *) linkage_name;
+      else
+	{
+	  gsymbol->name = obstack_alloc (&objfile->objfile_obstack, len + 1);
+	  memcpy (gsymbol->name, linkage_name, len);
+	  gsymbol->name[len] = '\0';
+	}
       gsymbol->language_specific.cplus_specific.demangled_name = NULL;
 
       return;
     }
 
+  if (objfile->demangled_names_hash == NULL)
+    create_demangled_names_hash (objfile);
+
   /* The stabs reader generally provides names that are not
      NUL-terminated; most of the other readers don't do this, so we
      can just use the given copy, unless we're in the Java case.  */
@@ -589,8 +627,10 @@ symbol_set_names (struct general_symbol_info *gsymbol,
       linkage_name_copy = linkage_name;
     }
 
-  slot = (char **) htab_find_slot (objfile->demangled_names_hash,
-				   lookup_name, INSERT);
+  entry.mangled = (char *) lookup_name;
+  slot = ((struct demangled_name_entry **)
+	  htab_find_slot (objfile->demangled_names_hash,
+			  &entry, INSERT));
 
   /* If this name is not in the hash table, add it.  */
   if (*slot == NULL)
@@ -599,25 +639,47 @@ symbol_set_names (struct general_symbol_info *gsymbol,
 							 linkage_name_copy);
       int demangled_len = demangled_name ? strlen (demangled_name) : 0;
 
-      /* If there is a demangled name, place it right after the mangled name.
-	 Otherwise, just place a second zero byte after the end of the mangled
-	 name.  */
-      *slot = obstack_alloc (&objfile->objfile_obstack,
-			     lookup_len + demangled_len + 2);
-      memcpy (*slot, lookup_name, lookup_len + 1);
+      /* Suppose we have demangled_name==NULL, original_len==-1, and
+	 lookup_name==linkage_name.  In this case, we already have the
+	 mangled name saved, and we don't have a demangled name.  So,
+	 you might think we could save a little space by not recording
+	 this in the hash table at all.
+	 
+	 It turns out that it is actually important to still save such
+	 an entry in the hash table, because storing this name gives
+	 us better bcache hit rates for partial symbols.  */
+      if (original_len == -1 && lookup_name == linkage_name)
+	{
+	  *slot = obstack_alloc (&objfile->objfile_obstack,
+				 sizeof (struct demangled_name_entry)
+				 + demangled_len);
+	  (*slot)->mangled = (char *) lookup_name;
+	}
+      else
+	{
+	  /* If we must copy the mangled name, put it directly after
+	     the demangled name so we can have a single
+	     allocation.  */
+	  *slot = obstack_alloc (&objfile->objfile_obstack,
+				 sizeof (struct demangled_name_entry)
+				 + lookup_len + demangled_len + 1);
+	  (*slot)->mangled = &((*slot)->demangled[demangled_len + 1]);
+	  strcpy ((*slot)->mangled, lookup_name);
+	}
+
       if (demangled_name != NULL)
 	{
-	  memcpy (*slot + lookup_len + 1, demangled_name, demangled_len + 1);
+	  strcpy ((*slot)->demangled, demangled_name);
 	  xfree (demangled_name);
 	}
       else
-	(*slot)[lookup_len + 1] = '\0';
+	(*slot)->demangled[0] = '\0';
     }
 
-  gsymbol->name = *slot + lookup_len - len;
-  if ((*slot)[lookup_len + 1] != '\0')
+  gsymbol->name = (*slot)->mangled;
+  if ((*slot)->demangled[0] != '\0')
     gsymbol->language_specific.cplus_specific.demangled_name
-      = &(*slot)[lookup_len + 1];
+      = (*slot)->demangled;
   else
     gsymbol->language_specific.cplus_specific.demangled_name = NULL;
 }
diff --git a/gdb/symtab.h b/gdb/symtab.h
index acb8510..2b53005 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -1121,6 +1121,11 @@ extern void prim_record_minimal_symbol (const char *, CORE_ADDR,
 					enum minimal_symbol_type,
 					struct objfile *);
 
+extern struct minimal_symbol *prim_record_minimal_symbol_full
+  (const char *, int, CORE_ADDR,
+   enum minimal_symbol_type,
+   int section, asection * bfd_section, struct objfile *);
+
 extern struct minimal_symbol *prim_record_minimal_symbol_and_info
   (const char *, CORE_ADDR,
    enum minimal_symbol_type,


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFC: save lots of memory
  2009-11-05  1:24 RFC: save lots of memory Tom Tromey
@ 2009-11-05 17:28 ` Joel Brobecker
  2009-12-27  3:40   ` Joel Brobecker
  2009-11-05 19:59 ` Daniel Jacobowitz
  1 sibling, 1 reply; 9+ messages in thread
From: Joel Brobecker @ 2009-11-05 17:28 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> This patch changes gdb so that such names are not copied.  This saves a
> lot of memory.  For example, I ran OO.o writer and attached to it with
> gdb (I have full debug info installed for OO.o and all its
> dependencies).

As discussed on IRC, I looked at the patch, and I think it is pretty
nice. The downside for the other formats seems reasonably small and
we have the options suggested by Tom in case we need to reclaim
the extra memory being consumed with the current approach.

I'm looking forward to measuring the impact on memory and performance
with one of the bigger apps we have in house :-).

-- 
Joel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFC: save lots of memory
  2009-11-05  1:24 RFC: save lots of memory Tom Tromey
  2009-11-05 17:28 ` Joel Brobecker
@ 2009-11-05 19:59 ` Daniel Jacobowitz
  2009-11-06 18:20   ` Tom Tromey
  1 sibling, 1 reply; 9+ messages in thread
From: Daniel Jacobowitz @ 2009-11-05 19:59 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Wed, Nov 04, 2009 at 06:23:54PM -0700, Tom Tromey wrote:
> Let me know what you think.

Generally seems sound.  There are two things I noticed:

* I don't think passing length == -1 is inherently ugly as a flag.
But it does seem silly to not pass the length when we often know it in
the caller.

* I can save you a couple more bytes:

> +	  *slot = obstack_alloc (&objfile->objfile_obstack,
> +				 sizeof (struct demangled_name_entry)
> +				 + demangled_len);

You want offsetof here, not sizeof.  The struct will have either three
or seven bytes of padding on most platforms, so you're pushing out to
a word boundary unnecessarily.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFC: save lots of memory
  2009-11-05 19:59 ` Daniel Jacobowitz
@ 2009-11-06 18:20   ` Tom Tromey
  2009-11-06 19:23     ` Paul Pluzhnikov
  2009-11-16 18:41     ` Tom Tromey
  0 siblings, 2 replies; 9+ messages in thread
From: Tom Tromey @ 2009-11-06 18:20 UTC (permalink / raw)
  To: gdb-patches

>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:

Daniel> * I don't think passing length == -1 is inherently ugly as a flag.
Daniel> But it does seem silly to not pass the length when we often know it in
Daniel> the caller.

Ok, I changed this.

Daniel> You want offsetof here, not sizeof.

Thanks, nice idea.

This patch implements both of these.
Built & regtested on x86-64 (compile farm).

I'll check this in next week if there are no further comments.

Tom

2009-11-06  Tom Tromey  <tromey@redhat.com>

	* xcoffread.c (scan_xcoff_symtab): Update.
	* symfile.h (add_psymbol_to_list): Update prototype.
	* symfile.c (add_psymbol_to_bcache): Add copy_name argument.
	(add_psymbol_to_list): Likewise.
	* stabsread.c (define_symbol): Update.
	* mdebugread.c (parse_partial_symbols): Update.
	(handle_psymbol_enumerators): Update.
	(new_symbol): Update.
	* dbxread.c (read_dbx_symtab): Update.
	* coffread.c (process_coff_symbol): Update.
	* symtab.h (prim_record_minimal_symbol_full): Declare.
	(SYMBOL_SET_NAMES): Add copy_name argument.
	* symtab.c (struct demangled_name_entry): New struct.
	(hash_demangled_name_entry): New function.
	(eq_demangled_name_entry): Likewise.
	(create_demangled_names_hash): Use new functions.
	(symbol_set_names): Use struct demangled_name_entry.  Add
	copy_name argument.
	* minsyms.c (prim_record_minimal_symbol_full): New function.
	(prim_record_minimal_symbol_and_info): Use it.
	* elfread.c (record_minimal_symbol): Add name_len and copy_name
	arguments.  Call prim_record_minimal_symbol_full.
	(elf_symtab_read): Add copy_names argument.
	(elf_symfile_read): Update calls to elf_symtab_read.
	* dwarf2read.c (add_partial_symbol): Don't copy symbol names.
	(load_partial_dies): Likewise.
	(new_symbol): Likewise.
	* cp-namespace.c (check_one_possible_namespace_symbol): Don't save
	name on the obstack.  Update call to SYMBOL_SET_NAMES.

diff --git a/gdb/coffread.c b/gdb/coffread.c
index 3e68698..98c563a 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -1503,7 +1503,7 @@ process_coff_symbol (struct coff_symbol *cs,
   name = cs->c_name;
   name = EXTERNAL_NAME (name, objfile->obfd);
   SYMBOL_LANGUAGE (sym) = current_subfile->language;
-  SYMBOL_SET_NAMES (sym, name, strlen (name), objfile);
+  SYMBOL_SET_NAMES (sym, name, strlen (name), 1, objfile);
 
   /* default assumptions */
   SYMBOL_VALUE (sym) = cs->c_value;
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index d2d8f2e..a7a387b 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -714,7 +714,6 @@ check_one_possible_namespace_symbol (const char *name, int len,
   if (sym == NULL)
     {
       struct type *type;
-      name_copy = obsavestring (name, len, &objfile->objfile_obstack);
 
       type = init_type (TYPE_CODE_NAMESPACE, 0, 0, name_copy, objfile);
 
@@ -723,7 +722,9 @@ check_one_possible_namespace_symbol (const char *name, int len,
       sym = obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol));
       memset (sym, 0, sizeof (struct symbol));
       SYMBOL_LANGUAGE (sym) = language_cplus;
-      SYMBOL_SET_NAMES (sym, name_copy, len, objfile);
+      /* Note that init_type copied the name to the objfile's
+	 obstack.  */
+      SYMBOL_SET_NAMES (sym, TYPE_NAME (type), len, 0, objfile);
       SYMBOL_CLASS (sym) = LOC_TYPEDEF;
       SYMBOL_TYPE (sym) = type;
       SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index 7cb016d..54d8b51 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -1,6 +1,6 @@
 /* Read dbx symbol tables and convert to internal format, for GDB.
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008.
+   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009.
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -1726,7 +1726,7 @@ pos %d"),
 		namestring = gdbarch_static_transform_name (gdbarch,
 							    namestring);
 
-	      add_psymbol_to_list (sym_name, sym_len,
+	      add_psymbol_to_list (sym_name, sym_len, 1,
 				   VAR_DOMAIN, LOC_STATIC,
 				   &objfile->static_psymbols,
 				   0, nlist.n_value,
@@ -1738,7 +1738,7 @@ pos %d"),
 					 data_sect_index);
 	      /* The addresses in these entries are reported to be
 		 wrong.  See the code that reads 'G's for symtabs. */
-	      add_psymbol_to_list (sym_name, sym_len,
+	      add_psymbol_to_list (sym_name, sym_len, 1,
 				   VAR_DOMAIN, LOC_STATIC,
 				   &objfile->global_psymbols,
 				   0, nlist.n_value,
@@ -1756,7 +1756,7 @@ pos %d"),
 		  || (p == namestring + 1
 		      && namestring[0] != ' '))
 		{
-		  add_psymbol_to_list (sym_name, sym_len,
+		  add_psymbol_to_list (sym_name, sym_len, 1,
 				       STRUCT_DOMAIN, LOC_TYPEDEF,
 				       &objfile->static_psymbols,
 				       nlist.n_value, 0,
@@ -1764,7 +1764,7 @@ pos %d"),
 		  if (p[2] == 't')
 		    {
 		      /* Also a typedef with the same name.  */
-		      add_psymbol_to_list (sym_name, sym_len,
+		      add_psymbol_to_list (sym_name, sym_len, 1,
 					   VAR_DOMAIN, LOC_TYPEDEF,
 					   &objfile->static_psymbols,
 					   nlist.n_value, 0,
@@ -1777,7 +1777,7 @@ pos %d"),
 	    case 't':
 	      if (p != namestring)	/* a name is there, not just :T... */
 		{
-		  add_psymbol_to_list (sym_name, sym_len,
+		  add_psymbol_to_list (sym_name, sym_len, 1,
 				       VAR_DOMAIN, LOC_TYPEDEF,
 				       &objfile->static_psymbols,
 				       nlist.n_value, 0,
@@ -1839,7 +1839,7 @@ pos %d"),
 			;
 		      /* Note that the value doesn't matter for
 			 enum constants in psymtabs, just in symtabs.  */
-		      add_psymbol_to_list (p, q - p,
+		      add_psymbol_to_list (p, q - p, 1,
 					   VAR_DOMAIN, LOC_CONST,
 					   &objfile->static_psymbols, 0,
 					   0, psymtab_language, objfile);
@@ -1857,7 +1857,7 @@ pos %d"),
 
 	    case 'c':
 	      /* Constant, e.g. from "const" in Pascal.  */
-	      add_psymbol_to_list (sym_name, sym_len,
+	      add_psymbol_to_list (sym_name, sym_len, 1,
 				   VAR_DOMAIN, LOC_CONST,
 				   &objfile->static_psymbols, nlist.n_value,
 				   0, psymtab_language, objfile);
@@ -1921,7 +1921,7 @@ pos %d"),
 		  pst->textlow = nlist.n_value;
 		  textlow_not_set = 0;
 		}
-	      add_psymbol_to_list (sym_name, sym_len,
+	      add_psymbol_to_list (sym_name, sym_len, 1,
 				   VAR_DOMAIN, LOC_BLOCK,
 				   &objfile->static_psymbols,
 				   0, nlist.n_value,
@@ -1989,7 +1989,7 @@ pos %d"),
 		  pst->textlow = nlist.n_value;
 		  textlow_not_set = 0;
 		}
-	      add_psymbol_to_list (sym_name, sym_len,
+	      add_psymbol_to_list (sym_name, sym_len, 1,
 				   VAR_DOMAIN, LOC_BLOCK,
 				   &objfile->global_psymbols,
 				   0, nlist.n_value,
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 9bf89d7..40a0f93 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -2417,6 +2417,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 	  /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
 	     mst_text, objfile); */
 	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+				      built_actual_name,
 				      VAR_DOMAIN, LOC_BLOCK,
 				      &objfile->global_psymbols,
 				      0, pdi->lowpc + baseaddr,
@@ -2427,6 +2428,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 	  /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
 	     mst_file_text, objfile); */
 	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+				      built_actual_name,
 				      VAR_DOMAIN, LOC_BLOCK,
 				      &objfile->static_psymbols,
 				      0, pdi->lowpc + baseaddr,
@@ -2453,6 +2455,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 	    addr = decode_locdesc (pdi->locdesc, cu);
 	  if (pdi->locdesc || pdi->has_type)
 	    psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+					built_actual_name,
 					VAR_DOMAIN, LOC_STATIC,
 					&objfile->global_psymbols,
 					0, addr + baseaddr,
@@ -2471,6 +2474,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 	  /*prim_record_minimal_symbol (actual_name, addr + baseaddr,
 	     mst_file_data, objfile); */
 	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+				      built_actual_name,
 				      VAR_DOMAIN, LOC_STATIC,
 				      &objfile->static_psymbols,
 				      0, addr + baseaddr,
@@ -2481,12 +2485,14 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
     case DW_TAG_base_type:
     case DW_TAG_subrange_type:
       add_psymbol_to_list (actual_name, strlen (actual_name),
+			   built_actual_name,
 			   VAR_DOMAIN, LOC_TYPEDEF,
 			   &objfile->static_psymbols,
 			   0, (CORE_ADDR) 0, cu->language, objfile);
       break;
     case DW_TAG_namespace:
       add_psymbol_to_list (actual_name, strlen (actual_name),
+			   built_actual_name,
 			   VAR_DOMAIN, LOC_TYPEDEF,
 			   &objfile->global_psymbols,
 			   0, (CORE_ADDR) 0, cu->language, objfile);
@@ -2511,6 +2517,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
       /* NOTE: carlton/2003-10-07: See comment in new_symbol about
 	 static vs. global.  */
       add_psymbol_to_list (actual_name, strlen (actual_name),
+			   built_actual_name,
 			   STRUCT_DOMAIN, LOC_TYPEDEF,
 			   (cu->language == language_cplus
 			    || cu->language == language_java)
@@ -2521,6 +2528,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
       break;
     case DW_TAG_enumerator:
       add_psymbol_to_list (actual_name, strlen (actual_name),
+			   built_actual_name,
 			   VAR_DOMAIN, LOC_CONST,
 			   (cu->language == language_cplus
 			    || cu->language == language_java)
@@ -6503,7 +6511,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
 	      || part_die->tag == DW_TAG_subrange_type))
 	{
 	  if (building_psymtab && part_die->name != NULL)
-	    add_psymbol_to_list (part_die->name, strlen (part_die->name),
+	    add_psymbol_to_list (part_die->name, strlen (part_die->name), 0,
 				 VAR_DOMAIN, LOC_TYPEDEF,
 				 &cu->objfile->static_psymbols,
 				 0, (CORE_ADDR) 0, cu->language, cu->objfile);
@@ -6524,7 +6532,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
 	  if (part_die->name == NULL)
 	    complaint (&symfile_complaints, _("malformed enumerator DIE ignored"));
 	  else if (building_psymtab)
-	    add_psymbol_to_list (part_die->name, strlen (part_die->name),
+	    add_psymbol_to_list (part_die->name, strlen (part_die->name), 0,
 				 VAR_DOMAIN, LOC_CONST,
 				 (cu->language == language_cplus
 				  || cu->language == language_java)
@@ -8304,7 +8312,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 
       /* Cache this symbol's name and the name's demangled form (if any).  */
       SYMBOL_LANGUAGE (sym) = cu->language;
-      SYMBOL_SET_NAMES (sym, name, strlen (name), objfile);
+      SYMBOL_SET_NAMES (sym, name, strlen (name), 0, objfile);
 
       /* Default assumptions.
          Use the passed type or decode it from the die.  */
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 131d7d2..86d2a78 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -172,7 +172,8 @@ elf_locate_sections (bfd *ignore_abfd, asection *sectp, void *eip)
 }
 
 static struct minimal_symbol *
-record_minimal_symbol (char *name, CORE_ADDR address,
+record_minimal_symbol (const char *name, int name_len, int copy_name,
+		       CORE_ADDR address,
 		       enum minimal_symbol_type ms_type,
 		       asection *bfd_section, struct objfile *objfile)
 {
@@ -181,8 +182,9 @@ record_minimal_symbol (char *name, CORE_ADDR address,
   if (ms_type == mst_text || ms_type == mst_file_text)
     address = gdbarch_smash_text_address (gdbarch, address);
 
-  return prim_record_minimal_symbol_and_info
-    (name, address, ms_type, bfd_section->index, bfd_section, objfile);
+  return prim_record_minimal_symbol_full (name, name_len, copy_name, address,
+					  ms_type, bfd_section->index,
+					  bfd_section, objfile);
 }
 
 /*
@@ -216,7 +218,8 @@ record_minimal_symbol (char *name, CORE_ADDR address,
 
 static void
 elf_symtab_read (struct objfile *objfile, int type,
-		 long number_of_symbols, asymbol **symbol_table)
+		 long number_of_symbols, asymbol **symbol_table,
+		 int copy_names)
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   long storage_needed;
@@ -297,7 +300,8 @@ elf_symtab_read (struct objfile *objfile, int type,
 	  symaddr += ANOFFSET (objfile->section_offsets, sect->index);
 
 	  msym = record_minimal_symbol
-	    ((char *) sym->name, symaddr, mst_solib_trampoline, sect, objfile);
+	    (sym->name, strlen (sym->name), copy_names,
+	     symaddr, mst_solib_trampoline, sect, objfile);
 	  if (msym != NULL)
 	    msym->filename = filesymname;
 	  continue;
@@ -510,7 +514,7 @@ elf_symtab_read (struct objfile *objfile, int type,
 	      continue;	/* Skip this symbol. */
 	    }
 	  msym = record_minimal_symbol
-	    ((char *) sym->name, symaddr,
+	    (sym->name, strlen (sym->name), copy_names, symaddr,
 	     ms_type, sym->section, objfile);
 
 	  if (msym)
@@ -545,15 +549,12 @@ elf_symtab_read (struct objfile *objfile, int type,
 
 	      if (len > 4 && strcmp (sym->name + len - 4, "@plt") == 0)
 		{
-		  char *base_name = xmalloc (len - 4 + 1);
 		  struct minimal_symbol *mtramp;
 
-		  memcpy (base_name, sym->name, len - 4);
-		  base_name[len - 4] = '\0';
-		  mtramp = record_minimal_symbol (base_name, symaddr,
+		  mtramp = record_minimal_symbol (sym->name, len - 4, 1,
+						  symaddr,
 						  mst_solib_trampoline,
 						  sym->section, objfile);
-		  xfree (base_name);
 		  if (mtramp)
 		    {
 		      MSYMBOL_SIZE (mtramp) = MSYMBOL_SIZE (msym);
@@ -638,7 +639,7 @@ elf_symfile_read (struct objfile *objfile, int mainline)
 	error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd),
 	       bfd_errmsg (bfd_get_error ()));
 
-      elf_symtab_read (objfile, ST_REGULAR, symcount, symbol_table);
+      elf_symtab_read (objfile, ST_REGULAR, symcount, symbol_table, 0);
     }
 
   /* Add the dynamic symbols.  */
@@ -656,7 +657,7 @@ elf_symfile_read (struct objfile *objfile, int mainline)
 	error (_("Can't read symbols from %s: %s"), bfd_get_filename (objfile->obfd),
 	       bfd_errmsg (bfd_get_error ()));
 
-      elf_symtab_read (objfile, ST_DYNAMIC, dynsymcount, dyn_symbol_table);
+      elf_symtab_read (objfile, ST_DYNAMIC, dynsymcount, dyn_symbol_table, 0);
     }
 
   /* Add synthetic symbols - for instance, names for any PLT entries.  */
@@ -674,7 +675,7 @@ elf_symfile_read (struct objfile *objfile, int mainline)
       for (i = 0; i < synthcount; i++)
 	synth_symbol_table[i] = synthsyms + i;
       make_cleanup (xfree, synth_symbol_table);
-      elf_symtab_read (objfile, ST_SYNTHETIC, synthcount, synth_symbol_table);
+      elf_symtab_read (objfile, ST_SYNTHETIC, synthcount, synth_symbol_table, 1);
     }
 
   /* Install any minimal symbols that have been collected as the current
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index aac82e9..c4331db 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -3097,7 +3097,7 @@ parse_partial_symbols (struct objfile *objfile)
 			  namestring = gdbarch_static_transform_name
 					 (gdbarch, namestring);
 
-			add_psymbol_to_list (namestring, p - namestring,
+			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_STATIC,
 					     &objfile->static_psymbols,
 					     0, sh.value,
@@ -3107,7 +3107,7 @@ parse_partial_symbols (struct objfile *objfile)
 			sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
 			/* The addresses in these entries are reported to be
 			   wrong.  See the code that reads 'G's for symtabs. */
-			add_psymbol_to_list (namestring, p - namestring,
+			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_STATIC,
 					     &objfile->global_psymbols,
 					     0, sh.value,
@@ -3125,7 +3125,7 @@ parse_partial_symbols (struct objfile *objfile)
 			    || (p == namestring + 1
 				&& namestring[0] != ' '))
 			  {
-			    add_psymbol_to_list (namestring, p - namestring,
+			    add_psymbol_to_list (namestring, p - namestring, 1,
 						 STRUCT_DOMAIN, LOC_TYPEDEF,
 						 &objfile->static_psymbols,
 						 sh.value, 0,
@@ -3134,6 +3134,7 @@ parse_partial_symbols (struct objfile *objfile)
 			      {
 				/* Also a typedef with the same name.  */
 				add_psymbol_to_list (namestring, p - namestring,
+						     1,
 						     VAR_DOMAIN, LOC_TYPEDEF,
 						     &objfile->static_psymbols,
 						     sh.value, 0,
@@ -3145,7 +3146,7 @@ parse_partial_symbols (struct objfile *objfile)
 		      case 't':
 			if (p != namestring)	/* a name is there, not just :T... */
 			  {
-			    add_psymbol_to_list (namestring, p - namestring,
+			    add_psymbol_to_list (namestring, p - namestring, 1,
 						 VAR_DOMAIN, LOC_TYPEDEF,
 						 &objfile->static_psymbols,
 						 sh.value, 0,
@@ -3207,7 +3208,7 @@ parse_partial_symbols (struct objfile *objfile)
 				  ;
 				/* Note that the value doesn't matter for
 				   enum constants in psymtabs, just in symtabs.  */
-				add_psymbol_to_list (p, q - p,
+				add_psymbol_to_list (p, q - p, 1,
 						     VAR_DOMAIN, LOC_CONST,
 						     &objfile->static_psymbols, 0,
 						     0, psymtab_language, objfile);
@@ -3224,7 +3225,7 @@ parse_partial_symbols (struct objfile *objfile)
 			continue;
 		      case 'c':
 			/* Constant, e.g. from "const" in Pascal.  */
-			add_psymbol_to_list (namestring, p - namestring,
+			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_CONST,
 					     &objfile->static_psymbols, sh.value,
 					     0, psymtab_language, objfile);
@@ -3241,7 +3242,7 @@ parse_partial_symbols (struct objfile *objfile)
 			    xfree (name);
 			  }
 			sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
-			add_psymbol_to_list (namestring, p - namestring,
+			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_BLOCK,
 					     &objfile->static_psymbols,
 					     0, sh.value,
@@ -3262,7 +3263,7 @@ parse_partial_symbols (struct objfile *objfile)
 			    xfree (name);
 			  }
 			sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
-			add_psymbol_to_list (namestring, p - namestring,
+			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_BLOCK,
 					     &objfile->global_psymbols,
 					     0, sh.value,
@@ -3491,12 +3492,12 @@ parse_partial_symbols (struct objfile *objfile)
 		     symbol table, and the MAIN__ symbol via the minimal
 		     symbol table.  */
 		  if (sh.st == stProc)
-		    add_psymbol_to_list (name, strlen (name),
+		    add_psymbol_to_list (name, strlen (name), 1,
 					 VAR_DOMAIN, LOC_BLOCK,
 					 &objfile->global_psymbols,
 				    0, sh.value, psymtab_language, objfile);
 		  else
-		    add_psymbol_to_list (name, strlen (name),
+		    add_psymbol_to_list (name, strlen (name), 1,
 					 VAR_DOMAIN, LOC_BLOCK,
 					 &objfile->static_psymbols,
 				    0, sh.value, psymtab_language, objfile);
@@ -3565,7 +3566,7 @@ parse_partial_symbols (struct objfile *objfile)
 		      && sh.iss != 0
 		      && sh.index != cur_sdx + 2)
 		    {
-		      add_psymbol_to_list (name, strlen (name),
+		      add_psymbol_to_list (name, strlen (name), 1,
 					   STRUCT_DOMAIN, LOC_TYPEDEF,
 					   &objfile->static_psymbols,
 					   0, (CORE_ADDR) 0,
@@ -3606,7 +3607,7 @@ parse_partial_symbols (struct objfile *objfile)
 		  continue;
 		}
 	      /* Use this gdb symbol */
-	      add_psymbol_to_list (name, strlen (name),
+	      add_psymbol_to_list (name, strlen (name), 1,
 				   VAR_DOMAIN, class,
 				   &objfile->static_psymbols,
 				   0, sh.value, psymtab_language, objfile);
@@ -3682,7 +3683,7 @@ parse_partial_symbols (struct objfile *objfile)
 		  break;
 		}
 	      name = debug_info->ssext + psh->iss;
-	      add_psymbol_to_list (name, strlen (name),
+	      add_psymbol_to_list (name, strlen (name), 1,
 				   VAR_DOMAIN, class,
 				   &objfile->global_psymbols,
 				   0, svalue,
@@ -3845,7 +3846,7 @@ handle_psymbol_enumerators (struct objfile *objfile, FDR *fh, int stype,
 
       /* Note that the value doesn't matter for enum constants
          in psymtabs, just in symtabs.  */
-      add_psymbol_to_list (name, strlen (name),
+      add_psymbol_to_list (name, strlen (name), 1,
 			   VAR_DOMAIN, LOC_CONST,
 			   &objfile->static_psymbols, 0,
 			   (CORE_ADDR) 0, psymtab_language, objfile);
@@ -4791,7 +4792,7 @@ new_symbol (char *name)
 
   memset (s, 0, sizeof (*s));
   SYMBOL_LANGUAGE (s) = psymtab_language;
-  SYMBOL_SET_NAMES (s, name, strlen (name), current_objfile);
+  SYMBOL_SET_NAMES (s, name, strlen (name), 1, current_objfile);
   return s;
 }
 
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index 64d20d2..393a0ea 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -757,11 +757,12 @@ prim_record_minimal_symbol (const char *name, CORE_ADDR address,
    newly created.  */
 
 struct minimal_symbol *
-prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
-				     enum minimal_symbol_type ms_type,
-				     int section,
-				     asection *bfd_section,
-				     struct objfile *objfile)
+prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name,
+				 CORE_ADDR address,
+				 enum minimal_symbol_type ms_type,
+				 int section,
+				 asection *bfd_section,
+				 struct objfile *objfile)
 {
   struct obj_section *obj_section;
   struct msym_bunch *new;
@@ -780,7 +781,10 @@ prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
   /* It's safe to strip the leading char here once, since the name
      is also stored stripped in the minimal symbol table. */
   if (name[0] == get_symbol_leading_char (objfile->obfd))
-    ++name;
+    {
+      ++name;
+      --name_len;
+    }
 
   if (ms_type == mst_file_text && strncmp (name, "__gnu_compiled", 14) == 0)
     return (NULL);
@@ -795,7 +799,7 @@ prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
   msymbol = &msym_bunch->contents[msym_bunch_index];
   SYMBOL_INIT_LANGUAGE_SPECIFIC (msymbol, language_unknown);
   SYMBOL_LANGUAGE (msymbol) = language_auto;
-  SYMBOL_SET_NAMES (msymbol, (char *)name, strlen (name), objfile);
+  SYMBOL_SET_NAMES (msymbol, name, name_len, copy_name, objfile);
 
   SYMBOL_VALUE_ADDRESS (msymbol) = address;
   SYMBOL_SECTION (msymbol) = section;
@@ -828,6 +832,21 @@ prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
   return msymbol;
 }
 
+/* Record a minimal symbol in the msym bunches.  Returns the symbol
+   newly created.  */
+
+struct minimal_symbol *
+prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
+				     enum minimal_symbol_type ms_type,
+				     int section,
+				     asection *bfd_section,
+				     struct objfile *objfile)
+{
+  return prim_record_minimal_symbol_full (name, strlen (name), 1,
+					  address, ms_type, section,
+					  bfd_section, objfile);
+}
+
 /* Compare two minimal symbols by address and return a signed result based
    on unsigned comparisons, so that we sort into unsigned numeric order.  
    Within groups with the same address, sort by name.  */
diff --git a/gdb/stabsread.c b/gdb/stabsread.c
index e62bb15..be91fc3 100644
--- a/gdb/stabsread.c
+++ b/gdb/stabsread.c
@@ -717,11 +717,11 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type,
 	}
       if (new_name != NULL)
 	{
-	  SYMBOL_SET_NAMES (sym, new_name, strlen (new_name), objfile);
+	  SYMBOL_SET_NAMES (sym, new_name, strlen (new_name), 1, objfile);
 	  xfree (new_name);
 	}
       else
-	SYMBOL_SET_NAMES (sym, string, p - string, objfile);
+	SYMBOL_SET_NAMES (sym, string, p - string, 1, objfile);
     }
   p++;
 
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 1e57c69..e696e33 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -3099,26 +3099,17 @@ start_psymtab_common (struct objfile *objfile,
    different domain (or address) is possible and correct.  */
 
 static const struct partial_symbol *
-add_psymbol_to_bcache (char *name, int namelength, domain_enum domain,
+add_psymbol_to_bcache (char *name, int namelength, int copy_name,
+		       domain_enum domain,
 		       enum address_class class,
 		       long val,	/* Value as a long */
 		       CORE_ADDR coreaddr,	/* Value as a CORE_ADDR */
 		       enum language language, struct objfile *objfile,
 		       int *added)
 {
-  char *buf = name;  
-  /* psymbol is static so that there will be no uninitialized gaps in the
-     structure which might contain random data, causing cache misses in
-     bcache. */
-  static struct partial_symbol psymbol;
-  
-  if (name[namelength] != '\0')
-    {
-      buf = alloca (namelength + 1);
-      /* Create local copy of the partial symbol */
-      memcpy (buf, name, namelength);
-      buf[namelength] = '\0';
-    }
+  struct partial_symbol psymbol;
+
+  memset (&psymbol, 0, sizeof (struct partial_symbol));
   /* val and coreaddr are mutually exclusive, one of them *will* be zero */
   if (val != 0)
     {
@@ -3133,7 +3124,7 @@ add_psymbol_to_bcache (char *name, int namelength, domain_enum domain,
   PSYMBOL_DOMAIN (&psymbol) = domain;
   PSYMBOL_CLASS (&psymbol) = class;
 
-  SYMBOL_SET_NAMES (&psymbol, buf, namelength, objfile);
+  SYMBOL_SET_NAMES (&psymbol, name, namelength, copy_name, objfile);
 
   /* Stash the partial symbol away in the cache */
   return bcache_full (&psymbol, sizeof (struct partial_symbol),
@@ -3170,7 +3161,8 @@ append_psymbol_to_list (struct psymbol_allocation_list *list,
    cache.  */
 
 const struct partial_symbol *
-add_psymbol_to_list (char *name, int namelength, domain_enum domain,
+add_psymbol_to_list (char *name, int namelength, int copy_name,
+		     domain_enum domain,
 		     enum address_class class,
 		     struct psymbol_allocation_list *list, 
 		     long val,	/* Value as a long */
@@ -3182,7 +3174,7 @@ add_psymbol_to_list (char *name, int namelength, domain_enum domain,
   int added;
 
   /* Stash the partial symbol away in the cache */
-  psym = add_psymbol_to_bcache (name, namelength, domain, class,
+  psym = add_psymbol_to_bcache (name, namelength, copy_name, domain, class,
 				val, coreaddr, language, objfile, &added);
 
   /* Do not duplicate global partial symbols.  */
diff --git a/gdb/symfile.h b/gdb/symfile.h
index 8c9249c..cf4d0a6 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -194,7 +194,7 @@ extern void extend_psymbol_list (struct psymbol_allocation_list *,
 /* #include "demangle.h" */
 
 extern const
-struct partial_symbol *add_psymbol_to_list (char *, int, domain_enum,
+struct partial_symbol *add_psymbol_to_list (char *, int, int, domain_enum,
 					    enum address_class,
 					    struct psymbol_allocation_list *,
 					    long, CORE_ADDR,
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 03586c3..5170932 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -427,6 +427,30 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
 
 /* Functions to initialize a symbol's mangled name.  */
 
+/* Objects of this type are stored in the demangled name hash table.  */
+struct demangled_name_entry
+{
+  char *mangled;
+  char demangled[1];
+};
+
+/* Hash function for the demangled name hash.  */
+static hashval_t
+hash_demangled_name_entry (const void *data)
+{
+  const struct demangled_name_entry *e = data;
+  return htab_hash_string (e->mangled);
+}
+
+/* Equality function for the demangled name hash.  */
+static int
+eq_demangled_name_entry (const void *a, const void *b)
+{
+  const struct demangled_name_entry *da = a;
+  const struct demangled_name_entry *db = b;
+  return strcmp (da->mangled, db->mangled) == 0;
+}
+
 /* Create the hash table used for demangled names.  Each hash entry is
    a pair of strings; one for the mangled name and one for the demangled
    name.  The entry is hashed via just the mangled name.  */
@@ -440,7 +464,7 @@ create_demangled_names_hash (struct objfile *objfile)
      1% in symbol reading.  */
 
   objfile->demangled_names_hash = htab_create_alloc
-    (256, htab_hash_string, (int (*) (const void *, const void *)) streq,
+    (256, hash_demangled_name_entry, eq_demangled_name_entry,
      NULL, xcalloc, xfree);
 }
 
@@ -496,10 +520,15 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 }
 
 /* Set both the mangled and demangled (if any) names for GSYMBOL based
-   on LINKAGE_NAME and LEN.  The hash table corresponding to OBJFILE
-   is used, and the memory comes from that objfile's objfile_obstack.
-   LINKAGE_NAME is copied, so the pointer can be discarded after
-   calling this function.  */
+   on LINKAGE_NAME and LEN.  Ordinarily, NAME is copied onto the
+   objfile's obstack; but if COPY_NAME is 0 and if NAME is
+   NUL-terminated, then this function assumes that NAME is already
+   correctly saved (either permanently or with a lifetime tied to the
+   objfile), and it will not be copied.
+
+   The hash table corresponding to OBJFILE is used, and the memory
+   comes from that objfile's objfile_obstack.  LINKAGE_NAME is copied,
+   so the pointer can be discarded after calling this function.  */
 
 /* We have to be careful when dealing with Java names: when we run
    into a Java minimal symbol, we don't know it's a Java symbol, so it
@@ -522,9 +551,10 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 
 void
 symbol_set_names (struct general_symbol_info *gsymbol,
-		  const char *linkage_name, int len, struct objfile *objfile)
+		  const char *linkage_name, int len, int copy_name,
+		  struct objfile *objfile)
 {
-  char **slot;
+  struct demangled_name_entry **slot;
   /* A 0-terminated copy of the linkage name.  */
   const char *linkage_name_copy;
   /* A copy of the linkage name that might have a special Java prefix
@@ -532,9 +562,7 @@ symbol_set_names (struct general_symbol_info *gsymbol,
   const char *lookup_name;
   /* The length of lookup_name.  */
   int lookup_len;
-
-  if (objfile->demangled_names_hash == NULL)
-    create_demangled_names_hash (objfile);
+  struct demangled_name_entry entry;
 
   if (gsymbol->language == language_ada)
     {
@@ -546,14 +574,22 @@ symbol_set_names (struct general_symbol_info *gsymbol,
          been observed with Java.  Because we don't store the demangled
          name with the symbol, we don't need to use the same trick
          as Java.  */
-      gsymbol->name = obstack_alloc (&objfile->objfile_obstack, len + 1);
-      memcpy (gsymbol->name, linkage_name, len);
-      gsymbol->name[len] = '\0';
+      if (!copy_name)
+	gsymbol->name = (char *) linkage_name;
+      else
+	{
+	  gsymbol->name = obstack_alloc (&objfile->objfile_obstack, len + 1);
+	  memcpy (gsymbol->name, linkage_name, len);
+	  gsymbol->name[len] = '\0';
+	}
       gsymbol->language_specific.cplus_specific.demangled_name = NULL;
 
       return;
     }
 
+  if (objfile->demangled_names_hash == NULL)
+    create_demangled_names_hash (objfile);
+
   /* The stabs reader generally provides names that are not
      NUL-terminated; most of the other readers don't do this, so we
      can just use the given copy, unless we're in the Java case.  */
@@ -589,8 +625,10 @@ symbol_set_names (struct general_symbol_info *gsymbol,
       linkage_name_copy = linkage_name;
     }
 
-  slot = (char **) htab_find_slot (objfile->demangled_names_hash,
-				   lookup_name, INSERT);
+  entry.mangled = (char *) lookup_name;
+  slot = ((struct demangled_name_entry **)
+	  htab_find_slot (objfile->demangled_names_hash,
+			  &entry, INSERT));
 
   /* If this name is not in the hash table, add it.  */
   if (*slot == NULL)
@@ -599,25 +637,49 @@ symbol_set_names (struct general_symbol_info *gsymbol,
 							 linkage_name_copy);
       int demangled_len = demangled_name ? strlen (demangled_name) : 0;
 
-      /* If there is a demangled name, place it right after the mangled name.
-	 Otherwise, just place a second zero byte after the end of the mangled
-	 name.  */
-      *slot = obstack_alloc (&objfile->objfile_obstack,
-			     lookup_len + demangled_len + 2);
-      memcpy (*slot, lookup_name, lookup_len + 1);
+      /* Suppose we have demangled_name==NULL, copy_name==0, and
+	 lookup_name==linkage_name.  In this case, we already have the
+	 mangled name saved, and we don't have a demangled name.  So,
+	 you might think we could save a little space by not recording
+	 this in the hash table at all.
+	 
+	 It turns out that it is actually important to still save such
+	 an entry in the hash table, because storing this name gives
+	 us better backache hit rates for partial symbols.  */
+      if (!copy_name && lookup_name == linkage_name)
+	{
+	  *slot = obstack_alloc (&objfile->objfile_obstack,
+				 offsetof (struct demangled_name_entry,
+					   demangled)
+				 + demangled_len + 1);
+	  (*slot)->mangled = (char *) lookup_name;
+	}
+      else
+	{
+	  /* If we must copy the mangled name, put it directly after
+	     the demangled name so we can have a single
+	     allocation.  */
+	  *slot = obstack_alloc (&objfile->objfile_obstack,
+				 offsetof (struct demangled_name_entry,
+					   demangled)
+				 + lookup_len + demangled_len + 2);
+	  (*slot)->mangled = &((*slot)->demangled[demangled_len + 1]);
+	  strcpy ((*slot)->mangled, lookup_name);
+	}
+
       if (demangled_name != NULL)
 	{
-	  memcpy (*slot + lookup_len + 1, demangled_name, demangled_len + 1);
+	  strcpy ((*slot)->demangled, demangled_name);
 	  xfree (demangled_name);
 	}
       else
-	(*slot)[lookup_len + 1] = '\0';
+	(*slot)->demangled[0] = '\0';
     }
 
-  gsymbol->name = *slot + lookup_len - len;
-  if ((*slot)[lookup_len + 1] != '\0')
+  gsymbol->name = (*slot)->mangled;
+  if ((*slot)->demangled[0] != '\0')
     gsymbol->language_specific.cplus_specific.demangled_name
-      = &(*slot)[lookup_len + 1];
+      = (*slot)->demangled;
   else
     gsymbol->language_specific.cplus_specific.demangled_name = NULL;
 }
diff --git a/gdb/symtab.h b/gdb/symtab.h
index acb8510..d5d0bf3 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -191,10 +191,10 @@ extern void symbol_init_language_specific (struct general_symbol_info *symbol,
 
 /* Set the linkage and natural names of a symbol, by demangling
    the linkage name.  */
-#define SYMBOL_SET_NAMES(symbol,linkage_name,len,objfile) \
-  symbol_set_names (&(symbol)->ginfo, linkage_name, len, objfile)
+#define SYMBOL_SET_NAMES(symbol,linkage_name,len,copy_name,objfile)	\
+  symbol_set_names (&(symbol)->ginfo, linkage_name, len, copy_name, objfile)
 extern void symbol_set_names (struct general_symbol_info *symbol,
-			      const char *linkage_name, int len,
+			      const char *linkage_name, int len, int copy_name,
 			      struct objfile *objfile);
 
 /* Now come lots of name accessor macros.  Short version as to when to
@@ -1121,6 +1121,11 @@ extern void prim_record_minimal_symbol (const char *, CORE_ADDR,
 					enum minimal_symbol_type,
 					struct objfile *);
 
+extern struct minimal_symbol *prim_record_minimal_symbol_full
+  (const char *, int, int, CORE_ADDR,
+   enum minimal_symbol_type,
+   int section, asection * bfd_section, struct objfile *);
+
 extern struct minimal_symbol *prim_record_minimal_symbol_and_info
   (const char *, CORE_ADDR,
    enum minimal_symbol_type,
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index c56ab86..a93fbd2 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -2606,7 +2606,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		  namestring = gdbarch_static_transform_name
 				 (gdbarch, namestring);
 
-		add_psymbol_to_list (namestring, p - namestring,
+		add_psymbol_to_list (namestring, p - namestring, 1,
 				     VAR_DOMAIN, LOC_STATIC,
 				     &objfile->static_psymbols,
 				     0, symbol.n_value,
@@ -2617,7 +2617,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		symbol.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
 		/* The addresses in these entries are reported to be
 		   wrong.  See the code that reads 'G's for symtabs. */
-		add_psymbol_to_list (namestring, p - namestring,
+		add_psymbol_to_list (namestring, p - namestring, 1,
 				     VAR_DOMAIN, LOC_STATIC,
 				     &objfile->global_psymbols,
 				     0, symbol.n_value,
@@ -2635,7 +2635,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		    || (p == namestring + 1
 			&& namestring[0] != ' '))
 		  {
-		    add_psymbol_to_list (namestring, p - namestring,
+		    add_psymbol_to_list (namestring, p - namestring, 1,
 					 STRUCT_DOMAIN, LOC_TYPEDEF,
 					 &objfile->static_psymbols,
 					 symbol.n_value, 0,
@@ -2643,7 +2643,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		    if (p[2] == 't')
 		      {
 			/* Also a typedef with the same name.  */
-			add_psymbol_to_list (namestring, p - namestring,
+			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_TYPEDEF,
 					     &objfile->static_psymbols,
 					     symbol.n_value, 0,
@@ -2656,7 +2656,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 	      case 't':
 		if (p != namestring)	/* a name is there, not just :T... */
 		  {
-		    add_psymbol_to_list (namestring, p - namestring,
+		    add_psymbol_to_list (namestring, p - namestring, 1,
 					 VAR_DOMAIN, LOC_TYPEDEF,
 					 &objfile->static_psymbols,
 					 symbol.n_value, 0,
@@ -2718,7 +2718,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 			  ;
 			/* Note that the value doesn't matter for
 			   enum constants in psymtabs, just in symtabs.  */
-			add_psymbol_to_list (p, q - p,
+			add_psymbol_to_list (p, q - p, 1,
 					     VAR_DOMAIN, LOC_CONST,
 					     &objfile->static_psymbols, 0,
 					     0, psymtab_language, objfile);
@@ -2736,7 +2736,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 
 	      case 'c':
 		/* Constant, e.g. from "const" in Pascal.  */
-		add_psymbol_to_list (namestring, p - namestring,
+		add_psymbol_to_list (namestring, p - namestring, 1,
 				     VAR_DOMAIN, LOC_CONST,
 				     &objfile->static_psymbols, symbol.n_value,
 				     0, psymtab_language, objfile);
@@ -2753,7 +2753,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		    xfree (name);
 		  }
 		symbol.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
-		add_psymbol_to_list (namestring, p - namestring,
+		add_psymbol_to_list (namestring, p - namestring, 1,
 				     VAR_DOMAIN, LOC_BLOCK,
 				     &objfile->static_psymbols,
 				     0, symbol.n_value,
@@ -2782,7 +2782,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		  continue;
 
 		symbol.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
-		add_psymbol_to_list (namestring, p - namestring,
+		add_psymbol_to_list (namestring, p - namestring, 1,
 				     VAR_DOMAIN, LOC_BLOCK,
 				     &objfile->global_psymbols,
 				     0, symbol.n_value,


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFC: save lots of memory
  2009-11-06 18:20   ` Tom Tromey
@ 2009-11-06 19:23     ` Paul Pluzhnikov
  2009-11-06 20:50       ` Tom Tromey
  2009-11-16 18:41     ` Tom Tromey
  1 sibling, 1 reply; 9+ messages in thread
From: Paul Pluzhnikov @ 2009-11-06 19:23 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Fri, Nov 6, 2009 at 10:19 AM, Tom Tromey <tromey@redhat.com> wrote:

> This patch implements both of these.

FYI:

patching file symfile.c
Hunk #1 FAILED at 3099.
Hunk #2 FAILED at 3124.
Hunk #3 succeeded at 3160 (offset -1 lines).
Hunk #4 succeeded at 3173 (offset -1 lines).
2 out of 4 hunks FAILED -- saving rejects to file symfile.c.rej




-- 
Paul Pluzhnikov


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFC: save lots of memory
  2009-11-06 19:23     ` Paul Pluzhnikov
@ 2009-11-06 20:50       ` Tom Tromey
  0 siblings, 0 replies; 9+ messages in thread
From: Tom Tromey @ 2009-11-06 20:50 UTC (permalink / raw)
  To: Paul Pluzhnikov; +Cc: gdb-patches

>>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes:

Paul> On Fri, Nov 6, 2009 at 10:19 AM, Tom Tromey <tromey@redhat.com> wrote:
>> This patch implements both of these.

Paul> FYI:

Paul> patching file symfile.c
Paul> Hunk #1 FAILED at 3099.
Paul> Hunk #2 FAILED at 3124.
Paul> Hunk #3 succeeded at 3160 (offset -1 lines).
Paul> Hunk #4 succeeded at 3173 (offset -1 lines).
Paul> 2 out of 4 hunks FAILED -- saving rejects to file symfile.c.rej

Oh, yeah, this patch didn't account for my recent other changes to
add_psymbol_to_bcache.  I can send a new patch if you want it.
Those changes don't affect memory use.

Tom


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFC: save lots of memory
  2009-11-06 18:20   ` Tom Tromey
  2009-11-06 19:23     ` Paul Pluzhnikov
@ 2009-11-16 18:41     ` Tom Tromey
  2009-11-16 22:14       ` Tom Tromey
  1 sibling, 1 reply; 9+ messages in thread
From: Tom Tromey @ 2009-11-16 18:41 UTC (permalink / raw)
  To: gdb-patches

>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:

Tom> I'll check this in next week if there are no further comments.

Committed.

Tom


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFC: save lots of memory
  2009-11-16 18:41     ` Tom Tromey
@ 2009-11-16 22:14       ` Tom Tromey
  0 siblings, 0 replies; 9+ messages in thread
From: Tom Tromey @ 2009-11-16 22:14 UTC (permalink / raw)
  To: gdb-patches

Tom> I'll check this in next week if there are no further comments.

Tom> Committed.

Keith pointed out that this caused some java regressions.

It turns out the gcj on the compile farm is not working.  That is why I
didn't notice this.

Anyway, I will be fixing these soon.

Tom


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFC: save lots of memory
  2009-11-05 17:28 ` Joel Brobecker
@ 2009-12-27  3:40   ` Joel Brobecker
  0 siblings, 0 replies; 9+ messages in thread
From: Joel Brobecker @ 2009-12-27  3:40 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> I'm looking forward to measuring the impact on memory and performance
> with one of the bigger apps we have in house :-).

I finally took the time to make some measurements.  The app I used has
about 600kSLOCs (with comments, it is a little over a million lines)
of Ada, builds and link to about 145MB of code and 70MB of debug info
making a grand total of 215MB.

    GDB startup time: 3.125s -> 2.369s => delta: -0.756s / -24.1 %
    Peak memory usage: 158.3MB -> 70.9MB => delta: -87.4MB / -55.0 %

    The same, but with -readnow:
    GDB startup time: 7.339s -> 6.461s => delta: 0.878s / - 11.9%
    Peak memory usage: 568.4MB -> 429.5MB => delta: -138.9MB / -24.4 %

Unsurprisingly, symbol lookup time did not appear to be affected either way.

I also quickly tried a patch suggested by Tom (attached), and got worse
results on both startup time and memory usage. No visible effect on lookup
performance. Not sure why, yet. I will keep the idea in mind, though.
For now, I must switch to something else again.

Impressive numbers nonetheless. This is a really nice catch, Tom!
-- 
Joel


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2009-12-27  3:40 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-05  1:24 RFC: save lots of memory Tom Tromey
2009-11-05 17:28 ` Joel Brobecker
2009-12-27  3:40   ` Joel Brobecker
2009-11-05 19:59 ` Daniel Jacobowitz
2009-11-06 18:20   ` Tom Tromey
2009-11-06 19:23     ` Paul Pluzhnikov
2009-11-06 20:50       ` Tom Tromey
2009-11-16 18:41     ` Tom Tromey
2009-11-16 22:14       ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox