[Ada] Add a symbol lookup cache

This patch implements the caching mechanism alluded to in a comment
next to some stubbed functions.

gdb/ChangeLog:

        * ada-lang.c (HASH_SIZE): New macro.
        (struct cache_entry): New type.
        (cache_space, cache): New static globals.
        (ada_clear_symbol_cache, find_entry): New functions.
        (lookup_cached_symbol, cache_symbol): Implement.
        (ada_new_objfile_observer, ada_free_objfile_observer): New.
        (_initialize_ada_language): Attach ada_new_objfile_observer
        and ada_free_objfile_observer.
This commit is contained in:
Joel Brobecker 2014-02-10 09:03:30 +04:00
parent f0c5f9b2b8
commit 3d9434b5dd
2 changed files with 143 additions and 3 deletions

View file

@ -1,3 +1,14 @@
2014-02-10 Joel Brobecker <brobecker@adacore.com>
* ada-lang.c (HASH_SIZE): New macro.
(struct cache_entry): New type.
(cache_space, cache): New static globals.
(ada_clear_symbol_cache, find_entry): New functions.
(lookup_cached_symbol, cache_symbol): Implement.
(ada_new_objfile_observer, ada_free_objfile_observer): New.
(_initialize_ada_language): Attach ada_new_objfile_observer
and ada_free_objfile_observer.
2014-02-10 Joel Brobecker <brobecker@adacore.com> 2014-02-10 Joel Brobecker <brobecker@adacore.com>
* ada-lang.c (ada_add_block_symbols, add_defn_to_vec) * ada-lang.c (ada_add_block_symbols, add_defn_to_vec)

View file

@ -4245,20 +4245,129 @@ make_array_descriptor (struct type *type, struct value *arr)
return descriptor; return descriptor;
} }
/* Dummy definitions for an experimental caching module that is not /* Symbol Cache Module */
* used in the public sources. */
/* This section implements a simple, fixed-sized hash table for those
Ada-mode symbols that get looked up in the course of executing the user's
commands. The size is fixed on the grounds that there are not
likely to be all that many symbols looked up during any given
session, regardless of the size of the symbol table. If we decide
to go to a resizable table, let's just use the stuff from libiberty
instead. */
/* Performance measurements made as of 2010-01-15 indicate that
this case does bring some noticeable improvements. Depending
on the type of entity being printed, the cache can make it as much
as an order of magnitude faster than without it.
The descriptive type DWARF extension has significantly reduced
the need for this cache, at least when DWARF is being used. However,
even in this case, some expensive name-based symbol searches are still
sometimes necessary - to find an XVZ variable, mostly. */
#define HASH_SIZE 1009
/* The result of a symbol lookup to be stored in our cache. */
struct cache_entry
{
/* The name used to perform the lookup. */
const char *name;
/* The namespace used during the lookup. */
domain_enum namespace;
/* The symbol returned by the lookup, or NULL if no matching symbol
was found. */
struct symbol *sym;
/* The block where the symbol was found, or NULL if no matching
symbol was found. */
const struct block *block;
/* A pointer to the next entry with the same hash. */
struct cache_entry *next;
};
/* An obstack used to store the entries in our cache. */
static struct obstack cache_space;
/* The root of the hash table used to implement our symbol cache. */
static struct cache_entry *cache[HASH_SIZE];
/* Clear all entries from the symbol cache. */
static void
ada_clear_symbol_cache (void)
{
obstack_free (&cache_space, NULL);
obstack_init (&cache_space);
memset (cache, '\000', sizeof (cache));
}
/* Search our cache for an entry matching NAME and NAMESPACE.
Return it if found, or NULL otherwise. */
static struct cache_entry **
find_entry (const char *name, domain_enum namespace)
{
int h = msymbol_hash (name) % HASH_SIZE;
struct cache_entry **e;
for (e = &cache[h]; *e != NULL; e = &(*e)->next)
{
if (namespace == (*e)->namespace && strcmp (name, (*e)->name) == 0)
return e;
}
return NULL;
}
/* Search the symbol cache for an entry matching NAME and NAMESPACE.
Return 1 if found, 0 otherwise.
If an entry was found and SYM is not NULL, set *SYM to the entry's
SYM. Same principle for BLOCK if not NULL. */
static int static int
lookup_cached_symbol (const char *name, domain_enum namespace, lookup_cached_symbol (const char *name, domain_enum namespace,
struct symbol **sym, const struct block **block) struct symbol **sym, const struct block **block)
{ {
return 0; struct cache_entry **e = find_entry (name, namespace);
if (e == NULL)
return 0;
if (sym != NULL)
*sym = (*e)->sym;
if (block != NULL)
*block = (*e)->block;
return 1;
} }
/* Assuming that (SYM, BLOCK) is the result of the lookup of NAME
in domain NAMESPACE, save this result in our symbol cache. */
static void static void
cache_symbol (const char *name, domain_enum namespace, struct symbol *sym, cache_symbol (const char *name, domain_enum namespace, struct symbol *sym,
const struct block *block) const struct block *block)
{ {
int h;
char *copy;
struct cache_entry *e;
/* If the symbol is a local symbol, then do not cache it, as a search
for that symbol depends on the context. To determine whether
the symbol is local or not, we check the block where we found it
against the global and static blocks of its associated symtab. */
if (sym
&& BLOCKVECTOR_BLOCK (BLOCKVECTOR (sym->symtab), GLOBAL_BLOCK) != block
&& BLOCKVECTOR_BLOCK (BLOCKVECTOR (sym->symtab), STATIC_BLOCK) != block)
return;
h = msymbol_hash (name) % HASH_SIZE;
e = (struct cache_entry *) obstack_alloc (&cache_space, sizeof (*e));
e->next = cache[h];
cache[h] = e;
e->name = copy = obstack_alloc (&cache_space, strlen (name) + 1);
strcpy (copy, name);
e->sym = sym;
e->namespace = namespace;
e->block = block;
} }
/* Symbol Lookup */ /* Symbol Lookup */
@ -13295,6 +13404,22 @@ initialize_ada_catchpoint_ops (void)
ops->print_recreate = print_recreate_catch_assert; ops->print_recreate = print_recreate_catch_assert;
} }
/* This module's 'new_objfile' observer. */
static void
ada_new_objfile_observer (struct objfile *objfile)
{
ada_clear_symbol_cache ();
}
/* This module's 'free_objfile' observer. */
static void
ada_free_objfile_observer (struct objfile *objfile)
{
ada_clear_symbol_cache ();
}
void void
_initialize_ada_language (void) _initialize_ada_language (void)
{ {
@ -13373,6 +13498,10 @@ DWARF attribute."),
(256, htab_hash_string, (int (*)(const void *, const void *)) streq, (256, htab_hash_string, (int (*)(const void *, const void *)) streq,
NULL, xcalloc, xfree); NULL, xcalloc, xfree);
/* The ada-lang observers. */
observer_attach_new_objfile (ada_new_objfile_observer);
observer_attach_free_objfile (ada_free_objfile_observer);
/* Setup per-inferior data. */ /* Setup per-inferior data. */
observer_attach_inferior_exit (ada_inferior_exit); observer_attach_inferior_exit (ada_inferior_exit);
ada_inferior_data ada_inferior_data