From 3d9434b5ddc141178be232048e3d944955cc1f91 Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Mon, 10 Feb 2014 09:03:30 +0400 Subject: [PATCH] [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. --- gdb/ChangeLog | 11 ++++ gdb/ada-lang.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 143 insertions(+), 3 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 940c6a223e7..828cb6e2b50 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2014-02-10 Joel Brobecker + + * 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 * ada-lang.c (ada_add_block_symbols, add_defn_to_vec) diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 269112c22c3..fc2c83b84cc 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -4245,20 +4245,129 @@ make_array_descriptor (struct type *type, struct value *arr) return descriptor; } -/* Dummy definitions for an experimental caching module that is not - * used in the public sources. */ + /* Symbol Cache Module */ + +/* 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 lookup_cached_symbol (const char *name, domain_enum namespace, 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 cache_symbol (const char *name, domain_enum namespace, struct symbol *sym, 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 */ @@ -13295,6 +13404,22 @@ initialize_ada_catchpoint_ops (void) 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 _initialize_ada_language (void) { @@ -13373,6 +13498,10 @@ DWARF attribute."), (256, htab_hash_string, (int (*)(const void *, const void *)) streq, 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. */ observer_attach_inferior_exit (ada_inferior_exit); ada_inferior_data -- 2.30.2