* aoutx.h (hash, compare, struct stringtab_entry, add_to_stringtab):

Use unsigned hash values for better hashing.
	(hash): Hash in the string length for long strings.
	* aoutx.h (compare): Replace 3 if's with a subtraction.
	(translate_to_native_sym_flags, add_to_stringtab): Reorder tests
	in decreasing order of success, as an optimization.
	(hash): Take a length arg; ignore chars after #25, for speed.
	(add_to_stringtab): Pass length to hash.
This commit is contained in:
David MacKenzie
1993-06-26 15:00:47 +00:00
parent fa02194747
commit 3caa6924bc
2 changed files with 105 additions and 56 deletions

View File

@ -1,3 +1,45 @@
Fri Jun 25 17:09:55 1993 David J. Mackenzie (djm@thepub.cygnus.com)
* aoutx.h (hash, compare, struct stringtab_entry, add_to_stringtab):
Use unsigned hash values for better hashing.
(hash): Hash in the string length for long strings.
Thu Jun 24 15:47:51 1993 David J. Mackenzie (djm@thepub.cygnus.com)
* aoutx.h (compare): Replace 3 if's with a subtraction.
(translate_to_native_sym_flags, add_to_stringtab): Reorder tests
in decreasing order of success, as an optimization.
(hash): Take a length arg; ignore chars after #25, for speed.
(add_to_stringtab): Pass length to hash.
Thu Jun 24 17:25:51 1993 Ken Raeburn (raeburn@poseidon.cygnus.com)
* elf32-sparc.c (sparc_reloc_map): Add SPARC_WDISP22 reloc.
* elfcode.h (elf_new_section_hook): Do nothing for now.
(elf_write_object_contents): Output common symbols the way ELF
wants them.
Wed Jun 23 16:20:07 1993 Ken Raeburn (raeburn@poseidon.cygnus.com)
* libelf.h (struct elf_obj_tdata and associated macros): Moved
here from elfcode.h. A couple of size-specific structure pointers
were changed to PTR; uses fixed appropriately.
(elf32_symbol_type, elf64_symbol_type): Separated definitions.
(bfd_elf_mkobject): Renamed from bfd_elf32_mkobject.
(bfd_elf32_mkobject, bfd_elf64_mkobject, elf_mkobject): New
temporary macros to ease name change.
* elf.c (elf_read, elf_mkobject, elf_get_str_section,
elf_string_from_elf_section, bfd_elf_find_section): Moved here
from elfcode.h.
* doc/Makefile.in (libbfd.h): Process elf.c too.
* Makefile.in (elf.o): Note new dependencies.
* elfcode.h: Lots of stuff moved elsewhere. Deleted some unused
code, tweaked some debug hooks.
(elf_slurp_reloca_table): Translate ELF section symbols into BFD
section symbols.
Wed Jun 23 11:34:21 1993 Jim Kingdon (kingdon@cygnus.com) Wed Jun 23 11:34:21 1993 Jim Kingdon (kingdon@cygnus.com)
* hosts/riscos.h: New file. * hosts/riscos.h: New file.

View File

@ -156,6 +156,9 @@ DESCRIPTION
reloc_howto_type howto_table_ext[] = reloc_howto_type howto_table_ext[] =
{ {
/* type rightshift size bitsize pc_ bit absol compl spec name partial_ src_ dst_ pcrel_
rela pos ute ain_on ial_ inplace mask mask offset
tive _overf fn */
HOWTO(RELOC_8, 0, 0, 8, false, 0, true, true,0,"8", false, 0,0x000000ff, false), HOWTO(RELOC_8, 0, 0, 8, false, 0, true, true,0,"8", false, 0,0x000000ff, false),
HOWTO(RELOC_16, 0, 1, 16, false, 0, true, true,0,"16", false, 0,0x0000ffff, false), HOWTO(RELOC_16, 0, 1, 16, false, 0, true, true,0,"16", false, 0,0x0000ffff, false),
HOWTO(RELOC_32, 0, 2, 32, false, 0, true, true,0,"32", false, 0,0xffffffff, false), HOWTO(RELOC_32, 0, 2, 32, false, 0, true, true,0,"32", false, 0,0xffffffff, false),
@ -1247,18 +1250,19 @@ DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd),
sym_pointer->e_type[0] &= ~N_TYPE; sym_pointer->e_type[0] &= ~N_TYPE;
if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) { /* We attempt to order these tests by decreasing frequency of success,
sym_pointer->e_type[0] |= N_BSS; according to tcov when linking the linker. */
} if (bfd_get_output_section(cache_ptr) == &bfd_abs_section) {
else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) { sym_pointer->e_type[0] |= N_ABS;
sym_pointer->e_type[0] |= N_DATA;
} }
else if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) { else if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
sym_pointer->e_type[0] |= N_TEXT; sym_pointer->e_type[0] |= N_TEXT;
} }
else if (bfd_get_output_section(cache_ptr) == &bfd_abs_section) else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
{ sym_pointer->e_type[0] |= N_DATA;
sym_pointer->e_type[0] |= N_ABS; }
else if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
sym_pointer->e_type[0] |= N_BSS;
} }
else if (bfd_get_output_section(cache_ptr) == &bfd_und_section) else if (bfd_get_output_section(cache_ptr) == &bfd_und_section)
{ {
@ -1295,12 +1299,12 @@ DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd),
(sym_pointer+1)->e_type[0] = 1; (sym_pointer+1)->e_type[0] = 1;
} }
if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
sym_pointer->e_type[0] |= N_EXT;
}
if (cache_ptr->flags & BSF_DEBUGGING) { if (cache_ptr->flags & BSF_DEBUGGING) {
sym_pointer->e_type[0] = ((aout_symbol_type *)cache_ptr)->type; sym_pointer->e_type[0] = ((aout_symbol_type *)cache_ptr)->type;
} }
else if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
sym_pointer->e_type[0] |= N_EXT;
}
if (cache_ptr->flags & BSF_CONSTRUCTOR) { if (cache_ptr->flags & BSF_CONSTRUCTOR) {
int type = ((aout_symbol_type *)cache_ptr)->type; int type = ((aout_symbol_type *)cache_ptr)->type;
switch (type) switch (type)
@ -1451,7 +1455,7 @@ DEFUN(NAME(aout,slurp_symbol_table),(abfd),
struct stringtab_entry { struct stringtab_entry {
/* Hash value for this string. Only useful so long as we aren't doing /* Hash value for this string. Only useful so long as we aren't doing
substring matches. */ substring matches. */
int hash; unsigned int hash;
/* Next node to look at, depending on whether the hash value of the string /* Next node to look at, depending on whether the hash value of the string
being searched for is less than or greater than the hash value of the being searched for is less than or greater than the hash value of the
@ -1535,23 +1539,28 @@ struct stringtab_data {
/* Some utility functions for the string table code. */ /* Some utility functions for the string table code. */
static INLINE int /* For speed, only hash on the first this many bytes of strings.
hash (string) This number was chosen by profiling ld linking itself, with -g. */
char *string; #define HASHMAXLEN 25
#define HASH_CHAR(c) (sum ^= sum >> 20, sum ^= sum << 7, sum += (c))
static INLINE unsigned int
hash (string, len)
unsigned char *string;
register unsigned int len;
{ {
unsigned int sum = 0; register unsigned int sum = 0;
while (*string)
if (len > HASHMAXLEN)
{ {
#if 0 HASH_CHAR (len);
/* This expression borrowed from some code in gnu make. */ len = HASHMAXLEN;
sum += *string++, sum = (sum << 7) + (sum >> 20); }
#endif
/* This appears to get a better distribution, at least for my one while (len--)
test case. Do some analysis on this later, get a real hash {
algorithm. */ HASH_CHAR (*string++);
sum ^= sum >> 20;
sum ^= sum << 7;
sum += *string++;
} }
return sum; return sum;
} }
@ -1581,15 +1590,9 @@ static INLINE int
compare (entry, str, hash) compare (entry, str, hash)
struct stringtab_entry *entry; struct stringtab_entry *entry;
CONST char *str; CONST char *str;
int hash; unsigned int hash;
{ {
if (hash == entry->hash) return hash - entry->hash;
return 0;
if (hash > entry->hash)
return 1;
if (hash < entry->hash)
return -1;
abort ();
} }
#ifdef GATHER_STATISTICS #ifdef GATHER_STATISTICS
@ -1623,8 +1626,8 @@ add_to_stringtab (abfd, str, tab, check)
int check; int check;
{ {
struct stringtab_entry **ep; struct stringtab_entry **ep;
struct stringtab_entry *entry; register struct stringtab_entry *entry;
int hashval, len; unsigned int hashval, len;
if (str[0] == 0) if (str[0] == 0)
{ {
@ -1662,7 +1665,7 @@ add_to_stringtab (abfd, str, tab, check)
zero. With a balanced tree, this wouldn't be very useful, but without it, zero. With a balanced tree, this wouldn't be very useful, but without it,
we might get a more even split at the top level, instead of skewing it we might get a more even split at the top level, instead of skewing it
badly should hash("/usr/lib/crt0.o") (or whatever) be far from zero. */ badly should hash("/usr/lib/crt0.o") (or whatever) be far from zero. */
hashval = hash (str) ^ tab->hash_zero; hashval = hash (str, len) ^ tab->hash_zero;
ep = &tab->strings; ep = &tab->strings;
if (!*ep) if (!*ep)
{ {
@ -1673,13 +1676,19 @@ add_to_stringtab (abfd, str, tab, check)
while (*ep) while (*ep)
{ {
int cmp; register int cmp;
entry = *ep; entry = *ep;
#ifdef GATHER_STATISTICS #ifdef GATHER_STATISTICS
tab->n_compares++; tab->n_compares++;
#endif #endif
cmp = compare (entry, str, hashval); cmp = compare (entry, str, hashval);
if (cmp == 0) /* The not-equal cases are more frequent, so check them first. */
if (cmp > 0)
ep = &entry->greater;
else if (cmp < 0)
ep = &entry->less;
else
{ {
if (entry->string == str) if (entry->string == str)
{ {
@ -1688,7 +1697,9 @@ add_to_stringtab (abfd, str, tab, check)
#endif #endif
goto match; goto match;
} }
if (!strcmp (entry->string, str)) /* Compare the first bytes to save a function call if they
don't match. */
if (entry->string[0] == str[0] && !strcmp (entry->string, str))
{ {
match: match:
#ifdef GATHER_STATISTICS #ifdef GATHER_STATISTICS
@ -1710,19 +1721,14 @@ add_to_stringtab (abfd, str, tab, check)
#endif #endif
ep = &entry->greater; ep = &entry->greater;
} }
else if (cmp > 0)
ep = &entry->greater;
else
/* cmp < 0 */
ep = &entry->less;
} }
/* If we get here, nothing that's in the table already matched. /* If we get here, nothing that's in the table already matched.
EP points to the `next' field at the end of the chain; stick a EP points to the `next' field at the end of the chain; stick a
new entry on here. */ new entry on here. */
add_it: add_it:
entry = (struct stringtab_entry *) bfd_alloc_by_size_t (abfd, entry = (struct stringtab_entry *)
sizeof (struct stringtab_entry)); bfd_alloc_by_size_t (abfd, sizeof (struct stringtab_entry));
entry->less = entry->greater = 0; entry->less = entry->greater = 0;
entry->hash = hashval; entry->hash = hashval;
@ -1794,7 +1800,8 @@ emit_strtab (abfd, tab)
double n_compares = tab->n_compares; double n_compares = tab->n_compares;
double avg_compares = n_compares / n_syms; double avg_compares = n_compares / n_syms;
/* The second value here should usually be near one. */ /* The second value here should usually be near one. */
fprintf (stderr, "\t average %f per symbol (%f * log2 nstrings)\n", fprintf (stderr,
"\t average %f comparisons per symbol (%f * log2 nstrings)\n",
avg_compares, avg_compares / log2 (count)); avg_compares, avg_compares / log2 (count));
} }
} }