Remove --reduce-memory-overheads and --hash-size arguments.

* NEWS: Mention --reduce-memory-overheads and --hash-size arguments
	options.
	* as.c: Remove the options from help.
	* doc/as.texi: Remove options.
	* doc/internals.texi: Remove hash from documentation.
	* hash.c (struct hash_entry): Remove.
	(struct hash_control): Likewise.
	(set_gas_hash_table_size): Likewise.
	(hash_new_sized): Likewise.
	(hash_new): Likewise.
	(hash_die): Likewise.
	(hash_lookup): Likewise.
	(hash_insert): Likewise.
	(hash_jam): Likewise.
	(hash_replace): Likewise.
	(hash_find): Likewise.
	(hash_find_n): Likewise.
	(hash_delete): Likewise.
	(hash_traverse): Likewise.
	(hash_print_statistics): Likewise.
	(TABLES): Likewise.
	(STATBUFSIZE): Likewise.
	(main): Likewise.
	(what): Likewise.
	(destroy): Likewise.
	(applicatee): Likewise.
	(whattable): Likewise.
	* hash.h (struct hash_control): Likewise.
	(set_gas_hash_table_size): Likewise.
	(hash_new): Likewise.
	(hash_new_sized): Likewise.
	(hash_die): Likewise.
	(hash_insert): Likewise.
	(hash_jam): Likewise.
	(hash_replace): Likewise.
	(hash_find): Likewise.
	(hash_find_n): Likewise.
	(hash_delete): Likewise.
	(hash_traverse): Likewise.
	(hash_print_statistics): Likewise.
This commit is contained in:
Martin Liska
2020-08-18 14:24:41 +02:00
committed by Alan Modra
parent 629310abec
commit a0522545b6
7 changed files with 47 additions and 704 deletions

View File

@ -1,3 +1,46 @@
2020-08-20 Martin Liska <mliska@suse.cz>
* NEWS: Mention --reduce-memory-overheads and --hash-size arguments
options.
* as.c: Remove the options from help.
* doc/as.texi: Remove options.
* doc/internals.texi: Remove hash from documentation.
* hash.c (struct hash_entry): Remove.
(struct hash_control): Likewise.
(set_gas_hash_table_size): Likewise.
(hash_new_sized): Likewise.
(hash_new): Likewise.
(hash_die): Likewise.
(hash_lookup): Likewise.
(hash_insert): Likewise.
(hash_jam): Likewise.
(hash_replace): Likewise.
(hash_find): Likewise.
(hash_find_n): Likewise.
(hash_delete): Likewise.
(hash_traverse): Likewise.
(hash_print_statistics): Likewise.
(TABLES): Likewise.
(STATBUFSIZE): Likewise.
(main): Likewise.
(what): Likewise.
(destroy): Likewise.
(applicatee): Likewise.
(whattable): Likewise.
* hash.h (struct hash_control): Likewise.
(set_gas_hash_table_size): Likewise.
(hash_new): Likewise.
(hash_new_sized): Likewise.
(hash_die): Likewise.
(hash_insert): Likewise.
(hash_jam): Likewise.
(hash_replace): Likewise.
(hash_find): Likewise.
(hash_find_n): Likewise.
(hash_delete): Likewise.
(hash_traverse): Likewise.
(hash_print_statistics): Likewise.
2020-08-20 Martin Liska <mliska@suse.cz>
* config/obj-coff-seh.c (seh_hash_insert): Port to use new

View File

@ -1,5 +1,8 @@
-*- text -*-
* Removed --reduce-memory-overheads and --hash-size as gas now
uses hash tables that can be expand and shrink automatically.
* Add {disp16} pseudo prefix to x86 assembler.
* Add support for Intel AMX instructions.

View File

@ -346,10 +346,6 @@ Options:\n\
fprintf (stream, _("\
--gdwarf-sections generate per-function section names for DWARF line information\n"));
fprintf (stream, _("\
--hash-size=<value> set the hash table size close to <value>\n"));
fprintf (stream, _("\
--help show this message and exit\n"));
fprintf (stream, _("\
--target-help show target specific options\n"));
fprintf (stream, _("\
-I DIR add DIR to search list for .include directives\n"));
@ -372,10 +368,6 @@ Options:\n\
fprintf (stream, _("\
-R fold data section into text section\n"));
fprintf (stream, _("\
--reduce-memory-overheads \n\
prefer smaller memory use at the cost of longer\n\
assembly times\n"));
fprintf (stream, _("\
--statistics print various measured statistics from execution\n"));
fprintf (stream, _("\
--strip-local-absolute strip local absolute symbols\n"));
@ -1100,22 +1092,10 @@ This program has absolutely no warranty.\n"));
break;
case OPTION_REDUCE_MEMORY_OVERHEADS:
/* The only change we make at the moment is to reduce
the size of the hash tables that we use. */
set_gas_hash_table_size (4051);
break;
case OPTION_HASH_TABLE_SIZE:
{
unsigned long new_size;
new_size = strtoul (optarg, NULL, 0);
if (new_size)
set_gas_hash_table_size (new_size);
else
as_fatal (_("--hash-size needs a numeric argument"));
break;
}
break;
}
}

View File

@ -238,7 +238,6 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}.
[@b{--listing-cont-lines}=@var{NUM}] [@b{--keep-locals}]
[@b{--no-pad-sections}]
[@b{-o} @var{objfile}] [@b{-R}]
[@b{--hash-size}=@var{NUM}] [@b{--reduce-memory-overheads}]
[@b{--statistics}]
[@b{-v}] [@b{-version}] [@b{--version}]
[@b{-W}] [@b{--warn}] [@b{--fatal-warnings}] [@b{-w}] [@b{-x}]
@ -875,18 +874,6 @@ Name the object-file output from @command{@value{AS}} @var{objfile}.
@item -R
Fold the data section into the text section.
@item --hash-size=@var{number}
Set the default size of GAS's hash tables to a prime number close to
@var{number}. Increasing this value can reduce the length of time it takes the
assembler to perform its tasks, at the expense of increasing the assembler's
memory requirements. Similarly reducing this value can reduce the memory
requirements at the expense of speed.
@item --reduce-memory-overheads
This option reduces GAS's memory requirements, at the expense of making the
assembly processes slower. Currently this switch is a synonym for
@samp{--hash-size=4051}, but in the future it may have other effects as well.
@ifset ELF
@item --sectname-subst
Honor substitution sequences in section names.

View File

@ -1915,38 +1915,6 @@ type is narrow enough, a decimal number will be produced; otherwise, it will be
in hexadecimal. The value itself is not examined to make this determination.
@end deftypefun
@node Hash tables
@subsection Hash tables
@cindex hash tables
@deftypefun @{@} @{struct hash_control *@} hash_new (void)
Creates the hash table control structure.
@end deftypefun
@deftypefun @{@} void hash_die (struct hash_control *)
Destroy a hash table.
@end deftypefun
@deftypefun @{@} void *hash_delete (struct hash_control *, const char *, int)
Deletes entry from the hash table, returns the value it had. If the last
arg is non-zero, free memory allocated for this entry and all entries
allocated more recently than this entry.
@end deftypefun
@deftypefun @{@} void *hash_replace (struct hash_control *, const char *, void *)
Updates the value for an entry already in the table, returning the old value.
If no entry was found, just returns NULL.
@end deftypefun
@deftypefun @{@} @{const char *@} hash_insert (struct hash_control *, const char *, void *)
Inserting a value already in the table is an error.
Returns an error message or NULL.
@end deftypefun
@deftypefun @{@} @{const char *@} hash_jam (struct hash_control *, const char *, void *)
Inserts if the value isn't already present, updates it if it is.
@end deftypefun
@node Test suite
@section Test suite
@cindex test suite

View File

@ -18,395 +18,7 @@
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
02110-1301, USA. */
/* This version of the hash table code is a wholescale replacement of
the old hash table code, which was fairly bad. This is based on
the hash table code in BFD, but optimized slightly for the
assembler. The assembler does not need to derive structures that
are stored in the hash table. Instead, it always stores a pointer.
The assembler uses the hash table mostly to store symbols, and we
don't need to confuse the symbol structure with a hash table
structure. */
#include "as.h"
#include "safe-ctype.h"
#include "obstack.h"
/* An entry in a hash table. */
struct hash_entry {
/* Next entry for this hash code. */
struct hash_entry *next;
/* String being hashed. */
const char *string;
/* Hash code. This is the full hash code, not the index into the
table. */
unsigned long hash;
/* Pointer being stored in the hash table. */
void *data;
};
/* A hash table. */
struct hash_control {
/* The hash array. */
struct hash_entry **table;
/* The number of slots in the hash table. */
unsigned int size;
/* An obstack for this hash table. */
struct obstack memory;
#ifdef HASH_STATISTICS
/* Statistics. */
unsigned long lookups;
unsigned long hash_compares;
unsigned long string_compares;
unsigned long insertions;
unsigned long replacements;
unsigned long deletions;
#endif /* HASH_STATISTICS */
};
/* The default number of entries to use when creating a hash table.
Note this value can be reduced to 4051 by using the command line
switch --reduce-memory-overheads, or set to other values by using
the --hash-size=<NUMBER> switch. */
static unsigned long gas_hash_table_size = 65537;
void
set_gas_hash_table_size (unsigned long size)
{
gas_hash_table_size = bfd_hash_set_default_size (size);
}
/* Create a hash table. This return a control block. */
struct hash_control *
hash_new_sized (unsigned long size)
{
unsigned long alloc;
struct hash_control *ret;
ret = XNEW (struct hash_control);
obstack_begin (&ret->memory, chunksize);
alloc = size * sizeof (struct hash_entry *);
ret->table = (struct hash_entry **) obstack_alloc (&ret->memory, alloc);
memset (ret->table, 0, alloc);
ret->size = size;
#ifdef HASH_STATISTICS
ret->lookups = 0;
ret->hash_compares = 0;
ret->string_compares = 0;
ret->insertions = 0;
ret->replacements = 0;
ret->deletions = 0;
#endif
return ret;
}
struct hash_control *
hash_new (void)
{
return hash_new_sized (gas_hash_table_size);
}
/* Delete a hash table, freeing all allocated memory. */
void
hash_die (struct hash_control *table)
{
obstack_free (&table->memory, 0);
free (table);
}
/* Look up a string in a hash table. This returns a pointer to the
hash_entry, or NULL if the string is not in the table. If PLIST is
not NULL, this sets *PLIST to point to the start of the list which
would hold this hash entry. If PHASH is not NULL, this sets *PHASH
to the hash code for KEY.
Each time we look up a string, we move it to the start of the list
for its hash code, to take advantage of referential locality. */
static struct hash_entry *
hash_lookup (struct hash_control *table, const char *key, size_t len,
struct hash_entry ***plist, unsigned long *phash)
{
unsigned long hash;
size_t n;
unsigned int c;
unsigned int hindex;
struct hash_entry **list;
struct hash_entry *p;
struct hash_entry *prev;
#ifdef HASH_STATISTICS
++table->lookups;
#endif
hash = 0;
for (n = 0; n < len; n++)
{
c = key[n];
hash += c + (c << 17);
hash ^= hash >> 2;
}
hash += len + (len << 17);
hash ^= hash >> 2;
if (phash != NULL)
*phash = hash;
hindex = hash % table->size;
list = table->table + hindex;
if (plist != NULL)
*plist = list;
prev = NULL;
for (p = *list; p != NULL; p = p->next)
{
#ifdef HASH_STATISTICS
++table->hash_compares;
#endif
if (p->hash == hash)
{
#ifdef HASH_STATISTICS
++table->string_compares;
#endif
if (strncmp (p->string, key, len) == 0 && p->string[len] == '\0')
{
if (prev != NULL)
{
prev->next = p->next;
p->next = *list;
*list = p;
}
return p;
}
}
prev = p;
}
return NULL;
}
/* Insert an entry into a hash table. This returns NULL on success.
On error, it returns a printable string indicating the error. It
is considered to be an error if the entry already exists in the
hash table. */
const char *
hash_insert (struct hash_control *table, const char *key, void *val)
{
struct hash_entry *p;
struct hash_entry **list;
unsigned long hash;
p = hash_lookup (table, key, strlen (key), &list, &hash);
if (p != NULL)
return "exists";
#ifdef HASH_STATISTICS
++table->insertions;
#endif
p = (struct hash_entry *) obstack_alloc (&table->memory, sizeof (*p));
p->string = key;
p->hash = hash;
p->data = val;
p->next = *list;
*list = p;
return NULL;
}
/* Insert or replace an entry in a hash table. This returns NULL on
success. On error, it returns a printable string indicating the
error. If an entry already exists, its value is replaced. */
const char *
hash_jam (struct hash_control *table, const char *key, void *val)
{
struct hash_entry *p;
struct hash_entry **list;
unsigned long hash;
p = hash_lookup (table, key, strlen (key), &list, &hash);
if (p != NULL)
{
#ifdef HASH_STATISTICS
++table->replacements;
#endif
p->data = val;
}
else
{
#ifdef HASH_STATISTICS
++table->insertions;
#endif
p = (struct hash_entry *) obstack_alloc (&table->memory, sizeof (*p));
p->string = key;
p->hash = hash;
p->data = val;
p->next = *list;
*list = p;
}
return NULL;
}
/* Replace an existing entry in a hash table. This returns the old
value stored for the entry. If the entry is not found in the hash
table, this does nothing and returns NULL. */
void *
hash_replace (struct hash_control *table, const char *key, void *value)
{
struct hash_entry *p;
void *ret;
p = hash_lookup (table, key, strlen (key), NULL, NULL);
if (p == NULL)
return NULL;
#ifdef HASH_STATISTICS
++table->replacements;
#endif
ret = p->data;
p->data = value;
return ret;
}
/* Find an entry in a hash table, returning its value. Returns NULL
if the entry is not found. */
void *
hash_find (struct hash_control *table, const char *key)
{
struct hash_entry *p;
p = hash_lookup (table, key, strlen (key), NULL, NULL);
if (p == NULL)
return NULL;
return p->data;
}
/* As hash_find, but KEY is of length LEN and is not guaranteed to be
NUL-terminated. */
void *
hash_find_n (struct hash_control *table, const char *key, size_t len)
{
struct hash_entry *p;
p = hash_lookup (table, key, len, NULL, NULL);
if (p == NULL)
return NULL;
return p->data;
}
/* Delete an entry from a hash table. This returns the value stored
for that entry, or NULL if there is no such entry. */
void *
hash_delete (struct hash_control *table, const char *key, int freeme)
{
struct hash_entry *p;
struct hash_entry **list;
p = hash_lookup (table, key, strlen (key), &list, NULL);
if (p == NULL)
return NULL;
if (p != *list)
abort ();
#ifdef HASH_STATISTICS
++table->deletions;
#endif
*list = p->next;
if (freeme)
obstack_free (&table->memory, p);
return p->data;
}
/* Traverse a hash table. Call the function on every entry in the
hash table. */
void
hash_traverse (struct hash_control *table,
void (*pfn) (const char *key, void *value))
{
unsigned int i;
for (i = 0; i < table->size; ++i)
{
struct hash_entry *p;
for (p = table->table[i]; p != NULL; p = p->next)
(*pfn) (p->string, p->data);
}
}
/* Print hash table statistics on the specified file. NAME is the
name of the hash table, used for printing a header. */
void
hash_print_statistics (FILE *f ATTRIBUTE_UNUSED,
const char *name ATTRIBUTE_UNUSED,
struct hash_control *table ATTRIBUTE_UNUSED)
{
#ifdef HASH_STATISTICS
unsigned int i;
unsigned long total;
unsigned long empty;
fprintf (f, "%s hash statistics:\n", name);
fprintf (f, "\t%lu lookups\n", table->lookups);
fprintf (f, "\t%lu hash comparisons\n", table->hash_compares);
fprintf (f, "\t%lu string comparisons\n", table->string_compares);
fprintf (f, "\t%lu insertions\n", table->insertions);
fprintf (f, "\t%lu replacements\n", table->replacements);
fprintf (f, "\t%lu deletions\n", table->deletions);
total = 0;
empty = 0;
for (i = 0; i < table->size; ++i)
{
struct hash_entry *p;
if (table->table[i] == NULL)
++empty;
else
{
for (p = table->table[i]; p != NULL; p = p->next)
++total;
}
}
fprintf (f, "\t%g average chain length\n", (double) total / table->size);
fprintf (f, "\t%lu empty slots\n", empty);
#endif
}
/* Insert ELEMENT into HTAB. If the element exists, it is overwritten. */
@ -431,189 +43,3 @@ htab_print_statistics (FILE *f, const char *name, htab_t table)
fprintf (f, "\t%lu elements\n", (unsigned long) htab_elements (table));
fprintf (f, "\t%lu table size\n", (unsigned long) htab_size (table));
}
#ifdef TEST
/* This test program is left over from the old hash table code. */
/* Number of hash tables to maintain (at once) in any testing. */
#define TABLES (6)
/* We can have 12 statistics. */
#define STATBUFSIZE (12)
/* Display statistics here. */
int statbuf[STATBUFSIZE];
/* Human farts here. */
char answer[100];
/* We test many hash tables at once. */
char *hashtable[TABLES];
/* Points to current hash_control. */
char *h;
char **pp;
char *p;
char *name;
char *value;
int size;
int used;
char command;
/* Number 0:TABLES-1 of current hashed symbol table. */
int number;
int
main ()
{
void applicatee ();
void destroy ();
char *what ();
int *ip;
number = 0;
h = 0;
printf ("type h <RETURN> for help\n");
for (;;)
{
printf ("hash_test command: ");
gets (answer);
command = answer[0];
command = TOLOWER (command); /* Ecch! */
switch (command)
{
case '#':
printf ("old hash table #=%d.\n", number);
whattable ();
break;
case '?':
for (pp = hashtable; pp < hashtable + TABLES; pp++)
{
printf ("address of hash table #%d control block is %xx\n",
pp - hashtable, *pp);
}
break;
case 'a':
hash_traverse (h, applicatee);
break;
case 'd':
hash_traverse (h, destroy);
hash_die (h);
break;
case 'f':
p = hash_find (h, name = what ("symbol"));
printf ("value of \"%s\" is \"%s\"\n", name, p ? p : "NOT-PRESENT");
break;
case 'h':
printf ("# show old, select new default hash table number\n");
printf ("? display all hashtable control block addresses\n");
printf ("a apply a simple display-er to each symbol in table\n");
printf ("d die: destroy hashtable\n");
printf ("f find value of nominated symbol\n");
printf ("h this help\n");
printf ("i insert value into symbol\n");
printf ("j jam value into symbol\n");
printf ("n new hashtable\n");
printf ("r replace a value with another\n");
printf ("s say what %% of table is used\n");
printf ("q exit this program\n");
printf ("x delete a symbol from table, report its value\n");
break;
case 'i':
p = hash_insert (h, name = what ("symbol"), value = what ("value"));
if (p)
{
printf ("symbol=\"%s\" value=\"%s\" error=%s\n", name, value,
p);
}
break;
case 'j':
p = hash_jam (h, name = what ("symbol"), value = what ("value"));
if (p)
{
printf ("symbol=\"%s\" value=\"%s\" error=%s\n", name, value, p);
}
break;
case 'n':
h = hashtable[number] = (char *) hash_new ();
break;
case 'q':
exit (EXIT_SUCCESS);
case 'r':
p = hash_replace (h, name = what ("symbol"), value = what ("value"));
printf ("old value was \"%s\"\n", p ? p : "{}");
break;
case 's':
hash_say (h, statbuf, STATBUFSIZE);
for (ip = statbuf; ip < statbuf + STATBUFSIZE; ip++)
{
printf ("%d ", *ip);
}
printf ("\n");
break;
case 'x':
p = hash_delete (h, name = what ("symbol"));
printf ("old value was \"%s\"\n", p ? p : "{}");
break;
default:
printf ("I can't understand command \"%c\"\n", command);
break;
}
}
}
char *
what (description)
char *description;
{
printf (" %s : ", description);
gets (answer);
return xstrdup (answer);
}
void
destroy (string, value)
char *string;
char *value;
{
free (string);
free (value);
}
void
applicatee (string, value)
char *string;
char *value;
{
printf ("%.20s-%.20s\n", string, value);
}
/* Determine number: what hash table to use.
Also determine h: points to hash_control. */
void
whattable ()
{
for (;;)
{
printf (" what hash table (%d:%d) ? ", 0, TABLES - 1);
gets (answer);
sscanf (answer, "%d", &number);
if (number >= 0 && number < TABLES)
{
h = hashtable[number];
if (!h)
{
printf ("warning: current hash-table-#%d. has no hash-control\n", number);
}
return;
}
else
{
printf ("invalid hash table number: %d\n", number);
}
}
}
#endif /* TEST */

View File

@ -21,70 +21,6 @@
#ifndef HASH_H
#define HASH_H
struct hash_control;
/* Set the size of the hash table used. */
void set_gas_hash_table_size (unsigned long);
/* Create a hash table. This return a control block. */
extern struct hash_control *hash_new (void);
extern struct hash_control *hash_new_sized (unsigned long);
/* Delete a hash table, freeing all allocated memory. */
extern void hash_die (struct hash_control *);
/* Insert an entry into a hash table. This returns NULL on success.
On error, it returns a printable string indicating the error. It
is considered to be an error if the entry already exists in the
hash table. */
extern const char *hash_insert (struct hash_control *,
const char *key, void *value);
/* Insert or replace an entry in a hash table. This returns NULL on
success. On error, it returns a printable string indicating the
error. If an entry already exists, its value is replaced. */
extern const char *hash_jam (struct hash_control *,
const char *key, void *value);
/* Replace an existing entry in a hash table. This returns the old
value stored for the entry. If the entry is not found in the hash
table, this does nothing and returns NULL. */
extern void *hash_replace (struct hash_control *, const char *key,
void *value);
/* Find an entry in a hash table, returning its value. Returns NULL
if the entry is not found. */
extern void *hash_find (struct hash_control *, const char *key);
/* As hash_find, but KEY is of length LEN and is not guaranteed to be
NUL-terminated. */
extern void *hash_find_n (struct hash_control *, const char *key, size_t len);
/* Delete an entry from a hash table. This returns the value stored
for that entry, or NULL if there is no such entry. */
extern void *hash_delete (struct hash_control *, const char *key, int);
/* Traverse a hash table. Call the function on every entry in the
hash table. */
extern void hash_traverse (struct hash_control *,
void (*pfn) (const char *key, void *value));
/* Print hash table statistics on the specified file. NAME is the
name of the hash table, used for printing a header. */
extern void hash_print_statistics (FILE *, const char *name,
struct hash_control *);
/* Insert ELEMENT into HTAB. If the element exists, it is overwritten. */
extern void htab_insert (htab_t, void *);