mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-01 22:34:22 +08:00
c4d840bdd6
This patch allows Ada to speed up symbol lookup by using the facilities in dictionary.[ch] for hashed lookups. First, we generalize dictionary search to allow clients to specify any matching function compatible with the hashing function. Next, we modify the hashing algorithm so that symbols that wild-match a name hash to the same value. Finally, we modify Ada symbol lookup to use these facilities. Because this patch touches on a hashing algorithm used by other languages, I took the precaution of doing a speed test on a list of about 12000 identifiers (repeatedly inserting all of them into a table and then doing a lookup on a million names at random, thus testing the speed of the hashing algorithm and how well it distributed names). There was actually a slight speedup, probably as a result of open- coding some of the tests in msymbol_hash_iw. By design, the revised hashing algorithm produces the same results as the original on most "normal" C identifiers. We considered augmenting the dictionary interface still further by allowing different hashing algorithms for different dictionaries, based on the (supposed) language of the symbols in that dictionary. While this produced better isolation of the changes to Ada programs, the additional flexibility also complicated the dictionary interface. I'd prefer to keep things simple for now. Tested w/o regressions on Linux i686. ChangeLog: gdb/ * ada-lang.c (ada_match_name): Use new API for wild_match. (wild_match): Change API to be consistent with that of strcmp_iw; return 0 for a match, and switch operand order. (full_match): New function. (ada_add_block_symbols): Use dict_iter_match_{first,next} for matching to allow use of hashing. * dictionary.c (struct dict_vector): Generalize iter_name_first, iter_name_next ot iter_match_first, iter_match_next. (iter_name_first_hashed): Replace with iter_match_first_hashed. (iter_name_next_hashed): Replace with iter_match_next_hashed. (iter_name_first_linear): Replace with iter_match_first_linear. (iter_name_next_linear): Replace with iter_match_next_linear. (dict_iter_name_first): Re-implement to use dict_iter_match_first. (dict_iter_name_next): Re-implement to use dict_iter_match_next. (dict_iter_match_first): New function. (dict_iter_match_next): New function. (dict_hash): New function. * dictionary.h (dict_iter_match_first, dict_iter_match_next): Declare. * psymtab.c (ada_lookup_partial_symbol): Use new wild_match API.
180 lines
6.6 KiB
C
180 lines
6.6 KiB
C
/* Routines for name->symbol lookups in GDB.
|
|
|
|
Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
|
|
|
Contributed by David Carlton <carlton@bactrian.org> and by Kealia,
|
|
Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef DICTIONARY_H
|
|
#define DICTIONARY_H
|
|
|
|
/* An opaque type for dictionaries; only dictionary.c should know
|
|
about its innards. */
|
|
|
|
struct dictionary;
|
|
|
|
/* Other types needed for declarations. */
|
|
|
|
struct symbol;
|
|
struct obstack;
|
|
struct pending;
|
|
|
|
|
|
/* The creation functions for various implementations of
|
|
dictionaries. */
|
|
|
|
/* Create a dictionary implemented via a fixed-size hashtable. All
|
|
memory it uses is allocated on OBSTACK; the environment is
|
|
initialized from SYMBOL_LIST. */
|
|
|
|
extern struct dictionary *dict_create_hashed (struct obstack *obstack,
|
|
const struct pending
|
|
*symbol_list);
|
|
|
|
/* Create a dictionary implemented via a hashtable that grows as
|
|
necessary. The dictionary is initially empty; to add symbols to
|
|
it, call dict_add_symbol(). Call dict_free() when you're done with
|
|
it. */
|
|
|
|
extern struct dictionary *dict_create_hashed_expandable (void);
|
|
|
|
/* Create a dictionary implemented via a fixed-size array. All memory
|
|
it uses is allocated on OBSTACK; the environment is initialized
|
|
from the SYMBOL_LIST. The symbols are ordered in the same order
|
|
that they're found in SYMBOL_LIST. */
|
|
|
|
extern struct dictionary *dict_create_linear (struct obstack *obstack,
|
|
const struct pending
|
|
*symbol_list);
|
|
|
|
/* Create a dictionary implemented via an array that grows as
|
|
necessary. The dictionary is initially empty; to add symbols to
|
|
it, call dict_add_symbol(). Call dict_free() when you're done with
|
|
it. */
|
|
|
|
extern struct dictionary *dict_create_linear_expandable (void);
|
|
|
|
|
|
/* The functions providing the interface to dictionaries. Note that
|
|
the most common parts of the interface, namely symbol lookup, are
|
|
only provided via iterator functions. */
|
|
|
|
/* Free the memory used by a dictionary that's not on an obstack. (If
|
|
any.) */
|
|
|
|
extern void dict_free (struct dictionary *dict);
|
|
|
|
/* Add a symbol to an expandable dictionary. */
|
|
|
|
extern void dict_add_symbol (struct dictionary *dict, struct symbol *sym);
|
|
|
|
/* Is the dictionary empty? */
|
|
|
|
extern int dict_empty (struct dictionary *dict);
|
|
|
|
/* A type containing data that is used when iterating over all symbols
|
|
in a dictionary. Don't ever look at its innards; this type would
|
|
be opaque if we didn't need to be able to allocate it on the
|
|
stack. */
|
|
|
|
struct dict_iterator
|
|
{
|
|
/* The dictionary that this iterator is associated to. */
|
|
const struct dictionary *dict;
|
|
/* The next two members are data that is used in a way that depends
|
|
on DICT's implementation type. */
|
|
int index;
|
|
struct symbol *current;
|
|
};
|
|
|
|
/* Initialize ITERATOR to point at the first symbol in DICT, and
|
|
return that first symbol, or NULL if DICT is empty. */
|
|
|
|
extern struct symbol *dict_iterator_first (const struct dictionary *dict,
|
|
struct dict_iterator *iterator);
|
|
|
|
/* Advance ITERATOR, and return the next symbol, or NULL if there are
|
|
no more symbols. Don't call this if you've previously received
|
|
NULL from dict_iterator_first or dict_iterator_next on this
|
|
iteration. */
|
|
|
|
extern struct symbol *dict_iterator_next (struct dict_iterator *iterator);
|
|
|
|
/* Initialize ITERATOR to point at the first symbol in DICT whose
|
|
SYMBOL_SEARCH_NAME is NAME (as tested using strcmp_iw), and return
|
|
that first symbol, or NULL if there are no such symbols. */
|
|
|
|
extern struct symbol *dict_iter_name_first (const struct dictionary *dict,
|
|
const char *name,
|
|
struct dict_iterator *iterator);
|
|
|
|
/* Advance ITERATOR to point at the next symbol in DICT whose
|
|
SYMBOL_SEARCH_NAME is NAME (as tested using strcmp_iw), or NULL if
|
|
there are no more such symbols. Don't call this if you've
|
|
previously received NULL from dict_iterator_first or
|
|
dict_iterator_next on this iteration. And don't call it unless
|
|
ITERATOR was created by a previous call to dict_iter_name_first
|
|
with the same NAME. */
|
|
|
|
extern struct symbol *dict_iter_name_next (const char *name,
|
|
struct dict_iterator *iterator);
|
|
|
|
/* Initialize ITERATOR to point at the first symbol in DICT whose
|
|
SYMBOL_SEARCH_NAME is NAME, as tested using COMPARE (which must use
|
|
the same conventions as strcmp_iw and be compatible with any
|
|
dictionary hashing function), and return that first symbol, or NULL
|
|
if there are no such symbols. */
|
|
|
|
extern struct symbol *dict_iter_match_first (const struct dictionary *dict,
|
|
const char *name,
|
|
int (*compare) (const char*,
|
|
const char *),
|
|
struct dict_iterator *iterator);
|
|
|
|
/* Advance ITERATOR to point at the next symbol in DICT whose
|
|
SYMBOL_SEARCH_NAME is NAME, as tested using COMPARE (see
|
|
dict_iter_match_first), or NULL if there are no more such symbols.
|
|
Don't call this if you've previously received NULL from
|
|
dict_iterator_match_first or dict_iterator_match_next on this
|
|
iteration. And don't call it unless ITERATOR was created by a
|
|
previous call to dict_iter_match_first with the same NAME and COMPARE. */
|
|
|
|
extern struct symbol *dict_iter_match_next (const char *name,
|
|
int (*compare) (const char*,
|
|
const char *),
|
|
struct dict_iterator *iterator);
|
|
|
|
/* Return some notion of the size of the dictionary: the number of
|
|
symbols if we have that, the number of hash buckets otherwise. */
|
|
|
|
extern int dict_size (const struct dictionary *dict);
|
|
|
|
/* Macro to loop through all symbols in a dictionary DICT, in no
|
|
particular order. ITER is a struct dict_iterator (NOTE: __not__ a
|
|
struct dict_iterator *), and SYM points to the current symbol.
|
|
|
|
It's implemented as a single loop, so you can terminate the loop
|
|
early by a break if you desire. */
|
|
|
|
#define ALL_DICT_SYMBOLS(dict, iter, sym) \
|
|
for ((sym) = dict_iterator_first ((dict), &(iter)); \
|
|
(sym); \
|
|
(sym) = dict_iterator_next (&(iter)))
|
|
|
|
#endif /* DICTIONARY_H */
|