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/intercu] Preserve DIE types


In multiple-compilation-unit land, we may read a particular compilation unit
from disk many times - once to build partial symbols, once to build full
symbols, and then for both partial and full symbols any number of additional
times after it falls out of cache.  For partial symbols this is fine; the
DIEs are self-contained.  All we want from them is their attributes.

If you take a look at struct die_info, though, you'll see the problem for
full symbols - the "type" field.  There is no way to repopulate the type
when we reread the symbols.  Not only would a lot of new lookup code have to
be written, but for nameless DIEs we're simply up a creek.

The only solution I could find was to cache this information, specifically
the DIE -> type mapping.  We could do it whenever the CU is flushed from
the cache for the first time, but I think the difference would be
negligible, so I build the hash table when each DIE is first assigned its
type.  This patch consists of code to create the hash table, code to
repopulate the type fields from the hash table (tested that it compiles, and
then #if'd it out, to prevent warnings about unused functions), and the
mechanical change to use set_die_type everywhere we used to assign to
die->type.  A forthcoming patch will remove the #if 0's; I just wanted to
break this chunk out so that it would be more readable.

Tested on i686-pc-linux-gnu.  OK?

-- 
Daniel Jacobowitz

2004-09-20  Daniel Jacobowitz  <dan@debian.org>

	* dwarf2read.c (struct dwarf2_per_cu_data): New field type_hash.
	(struct dwarf2_offset_and_type): New.
	(set_die_type, reset_die_and_siblings_types, get_die_type)
	(offset_and_type_hash, offset_and_type_eq): New functions.
	(read_structure_type, read_enumeration_type, read_array_type)
	(read_namespace, read_tag_pointer_type, read_tag_ptr_to_member_type)
	(read_tag_reference_type, read_tag_const_type)
	(read_tag_volatile_type, read_tag_string_type, read_subroutine_type)
	(read_typedef, read_base_type, read_subrange_type): Use
	set_die_type.

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.162
diff -u -p -r1.162 dwarf2read.c
--- dwarf2read.c	20 Sep 2004 22:26:19 -0000	1.162
+++ dwarf2read.c	21 Sep 2004 02:20:39 -0000
@@ -353,6 +353,13 @@ struct dwarf2_per_cu_data
 
   /* Set iff currently read in.  */
   struct dwarf2_cu *cu;
+
+  /* If full symbols for this CU have been read in, then this field
+     holds a map of DIE offsets to types.  It isn't always possible
+     to reconstruct this information later, so we have to preserve
+     it.  */
+
+  htab_t type_hash;
 };
 
 /* The line number information for a compilation unit (found in the
@@ -1035,6 +1042,14 @@ static void age_cached_comp_units (void)
 
 static void free_one_cached_comp_unit (void *);
 
+static void set_die_type (struct die_info *, struct type *,
+			  struct dwarf2_cu *);
+
+#if 0
+static void reset_die_and_siblings_types (struct die_info *,
+					  struct dwarf2_cu *);
+#endif
+
 static void create_all_comp_units (struct objfile *);
 
 static void dwarf2_mark (struct dwarf2_cu *);
@@ -3600,7 +3615,7 @@ read_structure_type (struct die_info *di
   /* We need to add the type field to the die immediately so we don't
      infinitely recurse when dealing with pointers to the structure
      type within the structure itself. */
-  die->type = type;
+  set_die_type (die, type, cu);
 
   if (die->child != NULL && ! die_is_declaration (die, cu))
     {
@@ -3776,7 +3791,7 @@ read_enumeration_type (struct die_info *
       TYPE_LENGTH (type) = 0;
     }
 
-  die->type = type;
+  set_die_type (die, type, cu);
 }
 
 /* Determine the name of the type represented by DIE, which should be
@@ -3942,7 +3957,8 @@ read_array_type (struct die_info *die, s
     {
       index_type = dwarf2_fundamental_type (objfile, FT_INTEGER, cu);
       range_type = create_range_type (NULL, index_type, 0, -1);
-      die->type = create_array_type (NULL, element_type, range_type);
+      set_die_type (die, create_array_type (NULL, element_type, range_type),
+		    cu);
       return;
     }
 
@@ -4002,7 +4018,7 @@ read_array_type (struct die_info *die, s
   do_cleanups (back_to);
 
   /* Install the type in the die. */
-  die->type = type;
+  set_die_type (die, type, cu);
 }
 
 static enum dwarf_array_dim_ordering
@@ -4129,7 +4145,7 @@ read_namespace (struct die_info *die, st
       TYPE_TAG_NAME (type) = TYPE_NAME (type);
 
       new_symbol (die, type, cu);
-      die->type = type;
+      set_die_type (die, type, cu);
 
       if (is_anonymous)
 	cp_add_using_directive (processing_current_prefix,
@@ -4236,7 +4252,7 @@ read_tag_pointer_type (struct die_info *
     }
 
   TYPE_LENGTH (type) = byte_size;
-  die->type = type;
+  set_die_type (die, type, cu);
 }
 
 /* Extract all information from a DW_TAG_ptr_to_member_type DIE and add to
@@ -4260,7 +4276,7 @@ read_tag_ptr_to_member_type (struct die_
   domain = die_containing_type (die, cu);
   smash_to_member_type (type, domain, to_type);
 
-  die->type = type;
+  set_die_type (die, type, cu);
 }
 
 /* Extract all information from a DW_TAG_reference_type DIE and add to
@@ -4288,7 +4304,7 @@ read_tag_reference_type (struct die_info
     {
       TYPE_LENGTH (type) = cu_header->addr_size;
     }
-  die->type = type;
+  set_die_type (die, type, cu);
 }
 
 static void
@@ -4302,7 +4318,8 @@ read_tag_const_type (struct die_info *di
     }
 
   base_type = die_type (die, cu);
-  die->type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
+  set_die_type (die, make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0),
+		cu);
 }
 
 static void
@@ -4316,7 +4333,8 @@ read_tag_volatile_type (struct die_info 
     }
 
   base_type = die_type (die, cu);
-  die->type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
+  set_die_type (die, make_cv_type (TYPE_CONST (base_type), 1, base_type, 0),
+		cu);
 }
 
 /* Extract all information from a DW_TAG_string_type DIE and add to
@@ -4368,7 +4386,7 @@ read_tag_string_type (struct die_info *d
       char_type = dwarf2_fundamental_type (objfile, FT_CHAR, cu);
       type = create_string_type (char_type, range_type);
     }
-  die->type = type;
+  set_die_type (die, type, cu);
 }
 
 /* Handle DIES due to C code like:
@@ -4450,7 +4468,7 @@ read_subroutine_type (struct die_info *d
 	}
     }
 
-  die->type = ftype;
+  set_die_type (die, ftype, cu);
 }
 
 static void
@@ -4467,7 +4485,9 @@ read_typedef (struct die_info *die, stru
 	{
 	  name = DW_STRING (attr);
 	}
-      die->type = init_type (TYPE_CODE_TYPEDEF, 0, TYPE_FLAG_TARGET_STUB, name, objfile);
+      set_die_type (die, init_type (TYPE_CODE_TYPEDEF, 0,
+				    TYPE_FLAG_TARGET_STUB, name, objfile),
+		    cu);
       TYPE_TARGET_TYPE (die->type) = die_type (die, cu);
     }
 }
@@ -4555,7 +4575,7 @@ read_base_type (struct die_info *die, st
     {
       type = dwarf_base_type (encoding, size, cu);
     }
-  die->type = type;
+  set_die_type (die, type, cu);
 }
 
 /* Read the given DW_AT_subrange DIE.  */
@@ -4626,7 +4646,7 @@ read_subrange_type (struct die_info *die
   if (attr)
     TYPE_LENGTH (range_type) = DW_UNSND (attr);
 
-  die->type = range_type;
+  set_die_type (die, range_type, cu);
 }
   
 
@@ -9252,6 +9272,105 @@ free_one_cached_comp_unit (void *target_
     }
 }
 
+/* A pair of DIE offset and GDB type pointer.  We store these
+   in a hash table separate from the DIEs, and preserve them
+   when the DIEs are flushed out of cache.  */
+
+struct dwarf2_offset_and_type
+{
+  unsigned int offset;
+  struct type *type;
+};
+
+/* Hash function for a dwarf2_offset_and_type.  */
+
+static hashval_t
+offset_and_type_hash (const void *item)
+{
+  const struct dwarf2_offset_and_type *ofs = item;
+  return ofs->offset;
+}
+
+/* Equality function for a dwarf2_offset_and_type.  */
+
+static int
+offset_and_type_eq (const void *item_lhs, const void *item_rhs)
+{
+  const struct dwarf2_offset_and_type *ofs_lhs = item_lhs;
+  const struct dwarf2_offset_and_type *ofs_rhs = item_rhs;
+  return ofs_lhs->offset == ofs_rhs->offset;
+}
+
+/* Set the type associated with DIE to TYPE.  Save it in CU's hash
+   table if necessary.  */
+
+static void
+set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
+{
+  struct dwarf2_offset_and_type **slot, ofs;
+
+  die->type = type;
+
+  if (cu->per_cu == NULL)
+    return;
+
+  if (cu->per_cu->type_hash == NULL)
+    cu->per_cu->type_hash
+      = htab_create_alloc_ex (cu->header.length / 24,
+			      offset_and_type_hash,
+			      offset_and_type_eq,
+			      NULL,
+			      &cu->objfile->objfile_obstack,
+			      hashtab_obstack_allocate,
+			      dummy_obstack_deallocate);
+
+  ofs.offset = die->offset;
+  ofs.type = type;
+  slot = (struct dwarf2_offset_and_type **)
+    htab_find_slot_with_hash (cu->per_cu->type_hash, &ofs, ofs.offset, INSERT);
+  *slot = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (**slot));
+  **slot = ofs;
+}
+
+#if 0
+
+/* Find the type for DIE in TYPE_HASH, or return NULL if DIE does not
+   have a saved type.  */
+
+static struct type *
+get_die_type (struct die_info *die, htab_t type_hash)
+{
+  struct dwarf2_offset_and_type *slot, ofs;
+
+  ofs.offset = die->offset;
+  slot = htab_find_with_hash (type_hash, &ofs, ofs.offset);
+  if (slot)
+    return slot->type;
+  else
+    return NULL;
+}
+
+/* Restore the types of the DIE tree starting at START_DIE from the hash
+   table saved in CU.  */
+
+static void
+reset_die_and_siblings_types (struct die_info *start_die, struct dwarf2_cu *cu)
+{
+  struct die_info *die;
+
+  if (cu->per_cu->type_hash == NULL)
+    return;
+
+  for (die = start_die; die != NULL; die = die->sibling)
+    {
+      die->type = get_die_type (die, cu->per_cu->type_hash);
+      if (die->child != NULL)
+	reset_die_and_siblings_types (die->child, cu);
+    }
+}
+
+#endif
+
 /* Set the mark field in CU and in every other compilation unit in the
    cache that we must keep because we are keeping CU.  */
 


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