Date: Fri, 18 Jan 2008 09:56:10 GMT From: John Birrell <jb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 133541 for review Message-ID: <200801180956.m0I9uAgj000614@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=133541 Change 133541 by jb@jb_freebsd1 on 2008/01/18 09:55:34 Add a hash table for DIEs for future use. Add a default name and use this when allocating every DIE. When an attribute value is found with DW_AT_name, get the pointer to the real name and use that. The use of __anon__ as the default name causes like DIEs to be matched when merging CTF data. The "die%d" name I was using caused an enormous number of type entries to be created and merged. The fact that the %d used a different number each time made it look like they were all different when in fact they weren't. We're down to the same order of magnitude of types in a GENERIC kernel as Solaris has in their 'genunix' kernel. This solves the performance problem I was seeing when running ctfmerge on the kernel object files. Affected files ... .. //depot/projects/dtrace/src/contrib/opensolaris/tools/ctf/cvt/dwarf.c#14 edit .. //depot/projects/dtrace/src/lib/libdwarf/_libdwarf.h#2 edit .. //depot/projects/dtrace/src/lib/libdwarf/dwarf_attrval.c#4 edit .. //depot/projects/dtrace/src/lib/libdwarf/dwarf_die.c#2 edit .. //depot/projects/dtrace/src/lib/libdwarf/dwarf_init.c#2 edit Differences ... ==== //depot/projects/dtrace/src/contrib/opensolaris/tools/ctf/cvt/dwarf.c#14 (text) ==== @@ -1370,13 +1370,8 @@ */ (void) die_unsigned(dw, base, DW_AT_byte_size, &sz, DW_ATTR_REQ); - if (tdp->t_name == NULL) { - /* terminate("die %llu: base type without name\n", off); */ - char dummy_name[64]; - snprintf(dummy_name, sizeof(dummy_name), "die%lx", (u_long) off); - debug(1, "die %llu: has no name. Using a dummy one: '%s'\n", off, dummy_name); - tdp->t_name = xstrdup(dummy_name); - } + if (tdp->t_name == NULL) + terminate("die %llu: base type without name\n", off); /* XXX make a name parser for float too */ if ((intr = die_base_name_parse(tdp->t_name, &new)) != NULL) { @@ -1684,14 +1679,8 @@ tdesc_add(dw, tdp); } - if (tdp != NULL) { + if (tdp != NULL) tdp->t_name = die_name(dw, die); - if (tdp->t_name == NULL) { - char dummy_name[64]; - snprintf(dummy_name, sizeof(dummy_name), "die%lx", (u_long) off); - tdp->t_name = xstrdup(dummy_name); - } - } dc->dc_create(dw, die, off, tdp); } ==== //depot/projects/dtrace/src/lib/libdwarf/_libdwarf.h#2 (text+ko) ==== @@ -56,6 +56,8 @@ #define DWARF_strtab 17 #define DWARF_DEBUG_SNAMES 18 +#define DWARF_DIE_HASH_SIZE 8191 + #define DWARF_SET_ERROR(_e, _err) do { \ _e->err_error = _err; \ _e->elf_error = 0; \ @@ -91,10 +93,13 @@ uint64_t die_abnum; /* Abbrev number. */ Dwarf_Abbrev die_a; /* Abbrev pointer. */ Dwarf_CU die_cu; /* Compilation unit pointer. */ + const char *die_name; /* Ptr to the name string. */ STAILQ_HEAD(, _Dwarf_AttrValue) die_attrval; /* List of attribute values. */ STAILQ_ENTRY(_Dwarf_Die) - die_next; /* Next die. */ + die_next; /* Next die in list. */ + STAILQ_ENTRY(_Dwarf_Die) + die_hash; /* Next die in hash table. */ }; struct _Dwarf_Attribute { @@ -130,6 +135,9 @@ cu_abbrev; /* List of abbrevs. */ STAILQ_HEAD(, _Dwarf_Die) cu_die; /* List of dies. */ + STAILQ_HEAD(, _Dwarf_Die) + cu_die_hash[DWARF_DIE_HASH_SIZE]; + /* Hash of dies. */ STAILQ_ENTRY(_Dwarf_CU) cu_next; /* Next compilation unit. */ }; ==== //depot/projects/dtrace/src/lib/libdwarf/dwarf_attrval.c#4 (text+ko) ==== @@ -60,6 +60,19 @@ /* Add the attribute value to the list in the die. */ STAILQ_INSERT_TAIL(&die->die_attrval, av, av_next); + /* Save a pointer to the attribute name if this is one. */ + if (av->av_attrib == DW_AT_name) + switch (av->av_form) { + case DW_FORM_strp: + die->die_name = av->u[1].s; + break; + case DW_FORM_string: + die->die_name = av->u[0].s; + break; + default: + break; + } + if (avp != NULL) *avp = av; @@ -118,7 +131,9 @@ *strp = NULL; - if ((av = dwarf_attrval_find(die, attr)) == NULL) { + if (attr == DW_AT_name) + *strp = die->die_name; + else if ((av = dwarf_attrval_find(die, attr)) == NULL) { DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); ret = DWARF_E_NO_ENTRY; } else { ==== //depot/projects/dtrace/src/lib/libdwarf/dwarf_die.c#2 (text+ko) ==== @@ -29,10 +29,13 @@ #include <stdlib.h> #include "_libdwarf.h" +static const char *anon_name = "__anon__"; + int dwarf_die_add(Dwarf_CU cu, int level, uint64_t offset, uint64_t abnum, Dwarf_Abbrev a, Dwarf_Die *diep, Dwarf_Error *err) { Dwarf_Die die; + uint64_t key; int ret = DWARF_E_NONE; if (err == NULL) @@ -54,6 +57,7 @@ die->die_abnum = abnum; die->die_a = a; die->die_cu = cu; + die->die_name = anon_name; /* Initialise the list of attribute values. */ STAILQ_INIT(&die->die_attrval); @@ -61,6 +65,10 @@ /* Add the die to the list in the compilation unit. */ STAILQ_INSERT_TAIL(&cu->cu_die, die, die_next); + /* Add the die to the hash table in the compilation unit. */ + key = offset % DWARF_DIE_HASH_SIZE; + STAILQ_INSERT_TAIL(&cu->cu_die_hash[key], die, die_hash); + if (diep != NULL) *diep = die; @@ -68,7 +76,7 @@ } int -dwarf_dieoffset(Dwarf_Die die __unused, Dwarf_Off *ret_offset, Dwarf_Error *err __unused) +dwarf_dieoffset(Dwarf_Die die, Dwarf_Off *ret_offset, Dwarf_Error *err __unused) { *ret_offset = die->die_offset; ==== //depot/projects/dtrace/src/lib/libdwarf/dwarf_init.c#2 (text+ko) ==== @@ -459,6 +459,7 @@ Dwarf_CU cu; Elf_Data *d = NULL; Elf_Scn *scn; + int i; int level = 0; int relocated = 0; int ret = DWARF_E_NONE; @@ -522,6 +523,10 @@ /* Initialise the list of dies. */ STAILQ_INIT(&cu->cu_die); + /* Initialise the hash table of dies. */ + for (i = 0; i < DWARF_DIE_HASH_SIZE; i++) + STAILQ_INIT(&cu->cu_die_hash[i]); + /* Add the compilation unit to the list. */ STAILQ_INSERT_TAIL(&dbg->dbg_cu, cu, cu_next);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200801180956.m0I9uAgj000614>