From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16017 invoked by alias); 25 Feb 2004 04:42:08 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 16005 invoked from network); 25 Feb 2004 04:42:06 -0000 Received: from unknown (HELO nevyn.them.org) (66.93.172.17) by sources.redhat.com with SMTP; 25 Feb 2004 04:42:06 -0000 Received: from drow by nevyn.them.org with local (Exim 4.30 #1 (Debian)) id 1Avqs2-0007ZX-9q; Tue, 24 Feb 2004 23:42:06 -0500 Date: Wed, 25 Feb 2004 04:42:00 -0000 From: Daniel Jacobowitz To: gdb-patches@sources.redhat.com Cc: Jim Blandy , Elena Zannoni Subject: [RFA/dwarf] Don't process types multiple times Message-ID: <20040225044206.GA23242@nevyn.them.org> Mail-Followup-To: gdb-patches@sources.redhat.com, Jim Blandy , Elena Zannoni Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.1i X-SW-Source: 2004-02/txt/msg00721.txt.bz2 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 * 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: