Micro-optimize abbrev reading and storage

Message ID 20210221060347.981277-1-tom@tromey.com
State New
Headers show
Series
  • Micro-optimize abbrev reading and storage
Related show

Commit Message

Tom Tromey Feb. 21, 2021, 6:03 a.m.
Currently, and abbrev_info points to a separately allocated array of
attr_abbrev objects.  This array is constructed in a temporary vector,
then copied to the abbrev table's obstack.

This patch changes abbrev_info to use the struct hack to store the
objects directly, and changes abbrev_table::read to avoid an extra
copy when allocating, using the "growing objects" capability of
obstacks.

This saves a bit of space, and also perhaps a little time.

gdb/ChangeLog
2021-02-20  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.c (read_attribute): Make 'abbrev' const.
	* dwarf2/abbrev.c (abbrev_table::alloc_abbrev): Remove.
	(abbrev_table::read): Update.
	* dwarf2/abbrev.h (struct attr_abbrev): Move earlier.
	(struct abbrev_info): Reformat.
	<attrs>: Now an array.
	(struct abbrev_table) <alloc_abbrev>: Remove.
---
 gdb/ChangeLog       | 10 +++++++
 gdb/dwarf2/abbrev.c | 71 +++++++++++++++++----------------------------
 gdb/dwarf2/abbrev.h | 42 ++++++++++++++-------------
 gdb/dwarf2/read.c   |  5 ++--
 4 files changed, 61 insertions(+), 67 deletions(-)

-- 
2.26.2

Patch

diff --git a/gdb/dwarf2/abbrev.c b/gdb/dwarf2/abbrev.c
index 6219c13a94b..9ece708a1ac 100644
--- a/gdb/dwarf2/abbrev.c
+++ b/gdb/dwarf2/abbrev.c
@@ -65,19 +65,6 @@  abbrev_table::abbrev_table (sect_offset off)
 {
 }
 
-/* Allocate space for a struct abbrev_info object in ABBREV_TABLE.  */
-
-struct abbrev_info *
-abbrev_table::alloc_abbrev ()
-{
-  struct abbrev_info *abbrev;
-
-  abbrev = XOBNEW (&m_abbrev_obstack, struct abbrev_info);
-  memset (abbrev, 0, sizeof (struct abbrev_info));
-
-  return abbrev;
-}
-
 /* Add an abbreviation to the table.  */
 
 void
@@ -97,11 +84,10 @@  abbrev_table::read (struct dwarf2_section_info *section,
   bfd *abfd = section->get_bfd_owner ();
   const gdb_byte *abbrev_ptr;
   struct abbrev_info *cur_abbrev;
-  unsigned int abbrev_number, bytes_read, abbrev_name;
-  unsigned int abbrev_form;
-  std::vector<struct attr_abbrev> cur_attrs;
+  unsigned int abbrev_number, bytes_read;
 
   abbrev_table_up abbrev_table (new struct abbrev_table (sect_off));
+  struct obstack *obstack = &abbrev_table->m_abbrev_obstack;
 
   /* Caller must ensure this.  */
   gdb_assert (section->readin);
@@ -112,56 +98,51 @@  abbrev_table::read (struct dwarf2_section_info *section,
   /* Loop until we reach an abbrev number of 0.  */
   while (abbrev_number)
     {
-      cur_attrs.clear ();
-      cur_abbrev = abbrev_table->alloc_abbrev ();
+      /* Start without any attrs.  */
+      obstack_blank (obstack, offsetof (abbrev_info, attrs));
+      cur_abbrev = (struct abbrev_info *) obstack_base (obstack);
 
-      /* read in abbrev header */
+      /* Read in abbrev header.  */
       cur_abbrev->number = abbrev_number;
       cur_abbrev->tag
-	= (enum dwarf_tag) read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+	= (enum dwarf_tag) read_unsigned_leb128 (abfd, abbrev_ptr,
+						 &bytes_read);
       abbrev_ptr += bytes_read;
       cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
       abbrev_ptr += 1;
 
-      /* now read in declarations */
+      /* Now read in declarations.  */
+      int num_attrs = 0;
       for (;;)
 	{
-	  LONGEST implicit_const;
+	  struct attr_abbrev cur_attr;
 
-	  abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+	  cur_attr.name
+	    = (enum dwarf_attribute) read_unsigned_leb128 (abfd, abbrev_ptr,
+							   &bytes_read);
 	  abbrev_ptr += bytes_read;
-	  abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+	  cur_attr.form
+	    = (enum dwarf_form) read_unsigned_leb128 (abfd, abbrev_ptr,
+						      &bytes_read);
 	  abbrev_ptr += bytes_read;
-	  if (abbrev_form == DW_FORM_implicit_const)
+	  if (cur_attr.form == DW_FORM_implicit_const)
 	    {
-	      implicit_const = read_signed_leb128 (abfd, abbrev_ptr,
-						   &bytes_read);
+	      cur_attr.implicit_const = read_signed_leb128 (abfd, abbrev_ptr,
+							    &bytes_read);
 	      abbrev_ptr += bytes_read;
 	    }
 	  else
-	    {
-	      /* Initialize it due to a false compiler warning.  */
-	      implicit_const = -1;
-	    }
+	    cur_attr.implicit_const = -1;
 
-	  if (abbrev_name == 0)
+	  if (cur_attr.name == 0)
 	    break;
 
-	  cur_attrs.emplace_back ();
-	  struct attr_abbrev &cur_attr = cur_attrs.back ();
-	  cur_attr.name = (enum dwarf_attribute) abbrev_name;
-	  cur_attr.form = (enum dwarf_form) abbrev_form;
-	  cur_attr.implicit_const = implicit_const;
+	  ++num_attrs;
+	  obstack_grow (obstack, &cur_attr, sizeof (cur_attr));
 	}
 
-      cur_abbrev->num_attrs = cur_attrs.size ();
-      cur_abbrev->attrs =
-	XOBNEWVEC (&abbrev_table->m_abbrev_obstack, struct attr_abbrev,
-		   cur_abbrev->num_attrs);
-      if (!cur_attrs.empty ())
-	memcpy (cur_abbrev->attrs, cur_attrs.data (),
-		cur_abbrev->num_attrs * sizeof (struct attr_abbrev));
-
+      cur_abbrev = (struct abbrev_info *) obstack_finish (obstack);
+      cur_abbrev->num_attrs = num_attrs;
       abbrev_table->add_abbrev (cur_abbrev);
 
       /* Get next abbreviation.
diff --git a/gdb/dwarf2/abbrev.h b/gdb/dwarf2/abbrev.h
index 8018f49cf08..e1d8b80619b 100644
--- a/gdb/dwarf2/abbrev.h
+++ b/gdb/dwarf2/abbrev.h
@@ -29,24 +29,30 @@ 
 
 #include "hashtab.h"
 
-/* This data structure holds the information of an abbrev.  */
-struct abbrev_info
-  {
-    unsigned int number;	/* number identifying abbrev */
-    enum dwarf_tag tag;		/* dwarf tag */
-    unsigned short has_children;		/* boolean */
-    unsigned short num_attrs;	/* number of attributes */
-    struct attr_abbrev *attrs;	/* an array of attribute descriptions */
-  };
-
 struct attr_abbrev
-  {
-    ENUM_BITFIELD(dwarf_attribute) name : 16;
-    ENUM_BITFIELD(dwarf_form) form : 16;
+{
+  ENUM_BITFIELD(dwarf_attribute) name : 16;
+  ENUM_BITFIELD(dwarf_form) form : 16;
 
-    /* It is valid only if FORM is DW_FORM_implicit_const.  */
-    LONGEST implicit_const;
-  };
+  /* It is valid only if FORM is DW_FORM_implicit_const.  */
+  LONGEST implicit_const;
+};
+
+/* This data structure holds the information of an abbrev.  */
+struct abbrev_info
+{
+  /* Number identifying abbrev.  */
+  unsigned int number;
+  /* DWARF tag.  */
+  enum dwarf_tag tag;
+  /* True if the DIE has children.  */
+  unsigned short has_children;
+  /* Number of attributes.  */
+  unsigned short num_attrs;
+  /* An array of attribute descriptions, allocated using the struct
+     hack.  */
+  struct attr_abbrev attrs[1];
+};
 
 struct abbrev_table;
 typedef std::unique_ptr<struct abbrev_table> abbrev_table_up;
@@ -85,10 +91,6 @@  struct abbrev_table
 
   DISABLE_COPY_AND_ASSIGN (abbrev_table);
 
-  /* Allocate space for a struct abbrev_info object in
-     ABBREV_TABLE.  */
-  struct abbrev_info *alloc_abbrev ();
-
   /* Add an abbreviation to the table.  */
   void add_abbrev (struct abbrev_info *abbrev);
 
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 51bf0fbeea5..b9be1eace78 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1340,7 +1340,8 @@  static const struct cu_partial_die_info find_partial_die (sect_offset, int,
 							  struct dwarf2_cu *);
 
 static const gdb_byte *read_attribute (const struct die_reader_specs *,
-				       struct attribute *, struct attr_abbrev *,
+				       struct attribute *,
+				       const struct attr_abbrev *,
 				       const gdb_byte *);
 
 static void read_attribute_reprocess (const struct die_reader_specs *reader,
@@ -20698,7 +20699,7 @@  read_attribute_value (const struct die_reader_specs *reader,
 
 static const gdb_byte *
 read_attribute (const struct die_reader_specs *reader,
-		struct attribute *attr, struct attr_abbrev *abbrev,
+		struct attribute *attr, const struct attr_abbrev *abbrev,
 		const gdb_byte *info_ptr)
 {
   attr->name = abbrev->name;