[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:
parent
f0c5f9b2b8
commit
3d9434b5dd
2 changed files with 143 additions and 3 deletions
|
@ -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)
|
||||||
|
|
135
gdb/ada-lang.c
135
gdb/ada-lang.c
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue