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]

[RFA/dwarf] Don't process types multiple times


This independent patch is a performance and correctness fix for full symbol
processing.  My description from the intercu branch posting:

 There are two ways that we can process a general DIE: process_die or
 read_type_die.  Children of particular DIE types may be processed directly,
 but these are the only major dispatch points.  It's interesting to notice
 that almost everything called from read_type_die starts with "if (die->type)
 return": everything but enumeration types and aggregate types, in fact.
 This means that if the first reference to an enumeration or aggregate type
 is a DW_AT_type or DW_AT_containing_type in a DIE numerically before the
 type's DIE, we'll end up calling new_symbol for it twice.

 Fixing this saves about 8% memory and 4% time from gdb -readnow libc.so.6,
 a lot of duplicate entries on maint print symbols which I vaguely recall
 being confused about but never investigated, and some serious problems for
 inter-CU support.  Without this, types could be added to the wrong symbol
 table.

Tested i686-pc-linux-gnu, no regressions.  OK to commit?

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

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

	* dwarf2read.c (read_structure_scope): Don't create a symbol
	or call process_die.  Return immediately if die->type is set.
	Call read_type_die before dwarf2_add_member_fn.
	(process_structure_scope): New function.
	(read_enumeration_type, read_enumeration_scope): New functions,
	broken out from read_enumeration.  Don't create the enumeration
	type if it has already been created.
	(read_enumeration): Removed.
	(process_die): Call process_structure_scope, read_enumeration_type,
	and read_enumeration_scope.  Just call new_symbol for base and
	subrange types.  Add a comment about other type dies.
	(read_type_die): Call read_enumeration_type.

Index: dwarf2read.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2read.c,v
retrieving revision 1.135
diff -u -p -r1.135 dwarf2read.c
--- dwarf2read.c	21 Feb 2004 02:13:35 -0000	1.135
+++ dwarf2read.c	25 Feb 2004 04:29:12 -0000
@@ -806,6 +806,8 @@ static void dwarf2_attach_fn_fields_to_t
 
 static void read_structure_scope (struct die_info *, struct dwarf2_cu *);
 
+static void process_structure_scope (struct die_info *, struct dwarf2_cu *);
+
 static void read_common_block (struct die_info *, struct dwarf2_cu *);
 
 static void read_namespace (struct die_info *die, struct dwarf2_cu *);
@@ -813,7 +815,9 @@ static void read_namespace (struct die_i
 static const char *namespace_name (struct die_info *die,
 				   int *is_anonymous, struct dwarf2_cu *);
 
-static void read_enumeration (struct die_info *, struct dwarf2_cu *);
+static void read_enumeration_type (struct die_info *, struct dwarf2_cu *);
+
+static void read_enumeration_scope (struct die_info *, struct dwarf2_cu *);
 
 static struct type *dwarf_base_type (int, int, struct dwarf2_cu *);
 
@@ -1950,10 +1954,16 @@ process_die (struct die_info *die, struc
     case DW_TAG_structure_type:
     case DW_TAG_union_type:
       read_structure_scope (die, cu);
+      process_structure_scope (die, cu);
       break;
     case DW_TAG_enumeration_type:
-      read_enumeration (die, cu);
+      read_enumeration_type (die, cu);
+      read_enumeration_scope (die, cu);
       break;
+
+    /* FIXME: These initialize die->type, but do not create a symbol
+       or process any children.  Therefore it doesn't do anything that
+       won't be done on-demand by read_type_die.  */
     case DW_TAG_subroutine_type:
       read_subroutine_type (die, cu);
       break;
@@ -1972,21 +1982,19 @@ process_die (struct die_info *die, struc
     case DW_TAG_string_type:
       read_tag_string_type (die, cu);
       break;
+    /* END FIXME */
+
     case DW_TAG_base_type:
       read_base_type (die, cu);
-      if (dwarf2_attr (die, DW_AT_name, cu))
-	{
-	  /* Add a typedef symbol for the base type definition.  */
-	  new_symbol (die, die->type, cu);
-	}
+      /* Add a typedef symbol for the type definition, if it has a
+	 DW_AT_name.  */
+      new_symbol (die, die->type, cu);
       break;
     case DW_TAG_subrange_type:
       read_subrange_type (die, cu);
-      if (dwarf2_attr (die, DW_AT_name, cu))
-       {
-         /* Add a typedef symbol for the base type definition.  */
-         new_symbol (die, die->type, cu);
-       }
+      /* Add a typedef symbol for the type definition, if it has a
+         DW_AT_name.  */
+      new_symbol (die, die->type, cu);
       break;
     case DW_TAG_common_block:
       read_common_block (die, cu);
@@ -3008,6 +3016,9 @@ read_structure_scope (struct die_info *d
      any.  */
   int need_to_update_name = 0;
 
+  if (die->type)
+    return;
+
   type = alloc_type (objfile);
 
   INIT_CPLUS_SPECIFIC (type);
@@ -3106,7 +3117,7 @@ read_structure_scope (struct die_info *d
 	  else if (child_die->tag == DW_TAG_subprogram)
 	    {
 	      /* C++ member function. */
-	      process_die (child_die, cu);
+	      read_type_die (child_die, cu);
 	      dwarf2_add_member_fn (&fi, child_die, type, cu);
 	      if (need_to_update_name)
 		{
@@ -3149,10 +3160,6 @@ read_structure_scope (struct die_info *d
 	      /* C++ base class field.  */
 	      dwarf2_add_field (&fi, child_die, cu);
 	    }
-	  else
-	    {
-	      process_die (child_die, cu);
-	    }
 	  child_die = sibling_die (child_die);
 	}
 
@@ -3209,8 +3216,6 @@ read_structure_scope (struct die_info *d
 	    }
 	}
 
-      new_symbol (die, type, cu);
-
       do_cleanups (back_to);
     }
   else
@@ -3224,26 +3229,53 @@ read_structure_scope (struct die_info *d
     do_cleanups (back_to);
 }
 
-/* Given a pointer to a die which begins an enumeration, process all
-   the dies that define the members of the enumeration.
+static void
+process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  const char *previous_prefix = processing_current_prefix;
 
-   This will be much nicer in draft 6 of the DWARF spec when our
-   members will be dies instead squished into the DW_AT_element_list
-   attribute.
+  if (TYPE_TAG_NAME (die->type) != NULL)
+    processing_current_prefix = TYPE_TAG_NAME (die->type);
 
-   NOTE: We reverse the order of the element list.  */
+  if (die->child != NULL && ! die_is_declaration (die, cu))
+    {
+      struct die_info *child_die;
+
+      child_die = die->child;
+
+      while (child_die && child_die->tag)
+	{
+	  if (child_die->tag == DW_TAG_member
+	      || child_die->tag == DW_TAG_variable
+	      || child_die->tag == DW_TAG_inheritance)
+	    {
+	      /* Do nothing.  */
+	    }
+	  else
+	    process_die (child_die, cu);
+
+	  child_die = sibling_die (child_die);
+	}
+
+      new_symbol (die, die->type, cu);
+    }
+
+  processing_current_prefix = previous_prefix;
+}
+
+/* Given a DW_AT_enumeration_type die, set its type.  We do not
+   complete the type's fields yet, or create any symbols.  */
 
 static void
-read_enumeration (struct die_info *die, struct dwarf2_cu *cu)
+read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
-  struct die_info *child_die;
   struct type *type;
-  struct field *fields;
   struct attribute *attr;
-  struct symbol *sym;
-  int num_fields;
-  int unsigned_enum = 1;
+
+  if (die->type)
+    return;
 
   type = alloc_type (objfile);
 
@@ -3278,6 +3310,26 @@ read_enumeration (struct die_info *die, 
       TYPE_LENGTH (type) = 0;
     }
 
+  die->type = type;
+}
+
+/* Given a pointer to a die which begins an enumeration, process all
+   the dies that define the members of the enumeration, and create the
+   symbol for the enumeration type.
+
+   NOTE: We reverse the order of the element list.  */
+
+static void
+read_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  struct die_info *child_die;
+  struct field *fields;
+  struct attribute *attr;
+  struct symbol *sym;
+  int num_fields;
+  int unsigned_enum = 1;
+
   num_fields = 0;
   fields = NULL;
   if (die->child != NULL)
@@ -3294,7 +3346,7 @@ read_enumeration (struct die_info *die, 
 	      attr = dwarf2_attr (child_die, DW_AT_name, cu);
 	      if (attr)
 		{
-		  sym = new_symbol (child_die, type, cu);
+		  sym = new_symbol (child_die, die->type, cu);
 		  if (SYMBOL_VALUE (sym) < 0)
 		    unsigned_enum = 0;
 
@@ -3321,18 +3373,18 @@ read_enumeration (struct die_info *die, 
 
       if (num_fields)
 	{
-	  TYPE_NFIELDS (type) = num_fields;
-	  TYPE_FIELDS (type) = (struct field *)
-	    TYPE_ALLOC (type, sizeof (struct field) * num_fields);
-	  memcpy (TYPE_FIELDS (type), fields,
+	  TYPE_NFIELDS (die->type) = num_fields;
+	  TYPE_FIELDS (die->type) = (struct field *)
+	    TYPE_ALLOC (die->type, sizeof (struct field) * num_fields);
+	  memcpy (TYPE_FIELDS (die->type), fields,
 		  sizeof (struct field) * num_fields);
 	  xfree (fields);
 	}
       if (unsigned_enum)
-	TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
+	TYPE_FLAGS (die->type) |= TYPE_FLAG_UNSIGNED;
     }
-  die->type = type;
-  new_symbol (die, type, cu);
+
+  new_symbol (die, die->type, cu);
 }
 
 /* Extract all information from a DW_TAG_array_type DIE and put it in
@@ -6012,7 +6064,7 @@ read_type_die (struct die_info *die, str
       read_structure_scope (die, cu);
       break;
     case DW_TAG_enumeration_type:
-      read_enumeration (die, cu);
+      read_enumeration_type (die, cu);
       break;
     case DW_TAG_subprogram:
     case DW_TAG_subroutine_type:


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