This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[intercu] Allocate abbrevs on an obstack


This patch changes the abbrevs to allocate from an obstack instead of
malloc.  Two interesting things here:

- It plugs a huge memory leak.  After loading partial symbols for
libc, GDB uses 5.6MB memory without this patch and 1.6MB with it.
We weren't emptying the abbrev table.

- I spent a lot of time trying to find alternate data structures that
would be more efficient.  The expandable hash table is slower, even if
you initially allocate it to the right size.  The splay tree I expected
to be quite good in this case, but it isn't either; the overhead is simply
too high.  The fixed-size ad-hoc hash table appears to be the best we can
do.

Committed to the intercu branch.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2004-02-21  Daniel Jacobowitz  <drow@mvista.com>

	* dwarf2read.c (struct dwarf2_cu): Add abbrev_obstack.
	(struct abbrev_info): Shorten two int flags.
	(dwarf_alloc_abbrev): Take a CU argument.
	(dwarf2_build_psymtabs_hard): Call dwarf2_empty_abbrev_table
	each time through the loop.  Update cleanup argument.
	(psymtab_to_symtab_1): Update cleanup argument.
	(dwarf2_read_abbrevs, dwarf2_alloc_abbrev): Allocate on the
	abbrev_obstack.
	(dwarf2_empty_abbrev_table): Just call obstack_free.

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.135.2.6
diff -u -p -r1.135.2.6 dwarf2read.c
--- dwarf2read.c	21 Feb 2004 20:50:11 -0000	1.135.2.6
+++ dwarf2read.c	21 Feb 2004 20:52:01 -0000
@@ -263,6 +263,8 @@ struct dwarf2_cu
 
   htab_t partial_dies;
   struct obstack partial_die_obstack;
+
+  struct obstack abbrev_obstack;
 };
 
 /* The line number information for a compilation unit (found in the
@@ -314,8 +316,8 @@ struct abbrev_info
   {
     unsigned int number;	/* number identifying abbrev */
     enum dwarf_tag tag;		/* dwarf tag */
-    int has_children;		/* boolean */
-    unsigned int num_attrs;	/* number of attributes */
+    unsigned short has_children;		/* boolean */
+    unsigned short num_attrs;	/* number of attributes */
     struct attr_abbrev *attrs;	/* an array of attribute descriptions */
     struct abbrev_info *next;	/* next in chain */
   };
@@ -923,7 +925,7 @@ static void dwarf2_free_tmp_obstack (voi
 
 static struct dwarf_block *dwarf_alloc_block (void);
 
-static struct abbrev_info *dwarf_alloc_abbrev (void);
+static struct abbrev_info *dwarf_alloc_abbrev (struct dwarf2_cu *);
 
 static struct die_info *dwarf_alloc_die (void);
 
@@ -1257,6 +1259,7 @@ dwarf2_build_psymtabs_hard (struct objfi
      left at all should be sufficient.  */
   while (info_ptr < dwarf_info_buffer + dwarf_info_size)
     {
+      struct cleanup *back_to_inner;
       struct dwarf2_cu cu;
       beg_of_comp_unit = info_ptr;
 
@@ -1296,7 +1299,7 @@ dwarf2_build_psymtabs_hard (struct objfi
 
       /* Read the abbrevs for this compilation unit into a table */
       dwarf2_read_abbrevs (abfd, &cu);
-      make_cleanup (dwarf2_empty_abbrev_table, cu.header.dwarf2_abbrevs);
+      back_to_inner = make_cleanup (dwarf2_empty_abbrev_table, &cu);
 
       /* Read the compilation unit die */
       info_ptr = load_partial_die (&comp_unit_die, abfd, info_ptr,
@@ -1387,6 +1390,8 @@ dwarf2_build_psymtabs_hard (struct objfi
 
       info_ptr = beg_of_comp_unit + cu.header.length 
                                   + cu.header.initial_length_size;
+
+      do_cleanups (back_to_inner);
     }
   do_cleanups (back_to);
 }
@@ -2041,7 +2046,7 @@ psymtab_to_symtab_1 (struct partial_symt
 
   /* Read the abbrevs for this compilation unit  */
   dwarf2_read_abbrevs (abfd, &cu);
-  make_cleanup (dwarf2_empty_abbrev_table, cu.header.dwarf2_abbrevs);
+  make_cleanup (dwarf2_empty_abbrev_table, &cu);
 
   cu.header.offset = offset;
 
@@ -4350,8 +4355,11 @@ dwarf2_read_abbrevs (bfd *abfd, struct d
   struct abbrev_info *cur_abbrev;
   unsigned int abbrev_number, bytes_read, abbrev_name;
   unsigned int abbrev_form, hash_number;
+  struct attr_abbrev *cur_attrs;
+  unsigned int allocated_attrs;
 
   /* Initialize dwarf2 abbrevs */
+  obstack_init (&cu->abbrev_obstack);
   memset (cu_header->dwarf2_abbrevs, 0,
           ABBREV_HASH_SIZE*sizeof (struct abbrev_info *));
 
@@ -4359,10 +4367,13 @@ dwarf2_read_abbrevs (bfd *abfd, struct d
   abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
   abbrev_ptr += bytes_read;
 
+  allocated_attrs = ATTR_ALLOC_CHUNK;
+  cur_attrs = xmalloc (allocated_attrs * sizeof (struct attr_abbrev));
+  
   /* loop until we reach an abbrev number of 0 */
   while (abbrev_number)
     {
-      cur_abbrev = dwarf_alloc_abbrev ();
+      cur_abbrev = dwarf_alloc_abbrev (cu);
 
       /* read in abbrev header */
       cur_abbrev->number = abbrev_number;
@@ -4378,21 +4389,27 @@ dwarf2_read_abbrevs (bfd *abfd, struct d
       abbrev_ptr += bytes_read;
       while (abbrev_name)
 	{
-	  if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0)
+	  if (cur_abbrev->num_attrs == allocated_attrs)
 	    {
-	      cur_abbrev->attrs = (struct attr_abbrev *)
-		xrealloc (cur_abbrev->attrs,
-			  (cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK)
-			  * sizeof (struct attr_abbrev));
+	      allocated_attrs += ATTR_ALLOC_CHUNK;
+	      cur_attrs
+		= xrealloc (cur_attrs, (allocated_attrs
+					* sizeof (struct attr_abbrev)));
 	    }
-	  cur_abbrev->attrs[cur_abbrev->num_attrs].name = abbrev_name;
-	  cur_abbrev->attrs[cur_abbrev->num_attrs++].form = abbrev_form;
+	  cur_attrs[cur_abbrev->num_attrs].name = abbrev_name;
+	  cur_attrs[cur_abbrev->num_attrs++].form = abbrev_form;
 	  abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
 	  abbrev_ptr += bytes_read;
 	  abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
 	  abbrev_ptr += bytes_read;
 	}
 
+      cur_abbrev->attrs = obstack_alloc (&cu->abbrev_obstack,
+					 (cur_abbrev->num_attrs
+					  * sizeof (struct attr_abbrev)));
+      memcpy (cur_abbrev->attrs, cur_attrs,
+	      cur_abbrev->num_attrs * sizeof (struct attr_abbrev));
+
       hash_number = abbrev_number % ABBREV_HASH_SIZE;
       cur_abbrev->next = cu_header->dwarf2_abbrevs[hash_number];
       cu_header->dwarf2_abbrevs[hash_number] = cur_abbrev;
@@ -4412,32 +4429,18 @@ dwarf2_read_abbrevs (bfd *abfd, struct d
       if (dwarf2_lookup_abbrev (abbrev_number, cu) != NULL)
 	break;
     }
+
+  xfree (cur_attrs);
 }
 
 /* Empty the abbrev table for a new compilation unit.  */
 
 static void
-dwarf2_empty_abbrev_table (void *ptr_to_abbrevs_table)
+dwarf2_empty_abbrev_table (void *ptr_to_cu)
 {
-  int i;
-  struct abbrev_info *abbrev, *next;
-  struct abbrev_info **abbrevs;
+  struct dwarf2_cu *cu = ptr_to_cu;
 
-  abbrevs = (struct abbrev_info **)ptr_to_abbrevs_table;
-
-  for (i = 0; i < ABBREV_HASH_SIZE; ++i)
-    {
-      next = NULL;
-      abbrev = abbrevs[i];
-      while (abbrev)
-	{
-	  next = abbrev->next;
-	  xfree (abbrev->attrs);
-	  xfree (abbrev);
-	  abbrev = next;
-	}
-      abbrevs[i] = NULL;
-    }
+  obstack_free (&cu->abbrev_obstack, NULL);
 }
 
 /* Lookup an abbrev_info structure in the abbrev hash table.  */
@@ -7957,11 +7960,12 @@ dwarf_alloc_block (void)
 }
 
 static struct abbrev_info *
-dwarf_alloc_abbrev (void)
+dwarf_alloc_abbrev (struct dwarf2_cu *cu)
 {
   struct abbrev_info *abbrev;
 
-  abbrev = (struct abbrev_info *) xmalloc (sizeof (struct abbrev_info));
+  abbrev = (struct abbrev_info *)
+    obstack_alloc (&cu->abbrev_obstack, sizeof (struct abbrev_info));
   memset (abbrev, 0, sizeof (struct abbrev_info));
   return (abbrev);
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]