From: Doug Evans <dje@google.com>
To: sami wagiaalla <swagiaal@redhat.com>
Cc: gdb-patches@sourceware.org
Subject: Re: [RFC] Use custom hash function with bcache
Date: Mon, 16 Aug 2010 18:29:00 -0000 [thread overview]
Message-ID: <AANLkTikH1rBzysO-nNT-w3a0me7zMcGfSpn7+7oJQdWk@mail.gmail.com> (raw)
In-Reply-To: <4C6946E1.6000709@redhat.com>
On Mon, Aug 16, 2010 at 7:10 AM, sami wagiaalla <swagiaal@redhat.com> wrote:
> This patch enables the use of custom hash and comparison functions when
> adding elements to a bcache. The patch also introduces hash and comparison
> functions which take into consideration only the relevant properties of the
> psymbol.
>
> Tested by running the test suit on F13 with gcc 4.4.4 on x8664, no
> regressions.
>
> also used 'main print statistics' to ensure that the bcache object count and
> unique object count are as expected with a small test case.
>
> Sami
>
Hi. Comments inline with the patch.
2010-08-13 Sami Wagiaalla <swagiaal@redhat.com>
* psymtab.c (psymbol_hash): New function.
(psymbol_compare): New function.
(add_psymbol_to_bcache): pass psymbol_hash and psymbol_compare
to bcache_full.
* bcache.c (hash_continue): New.
(hash): Use hash_continue.
(bcache): Now takes hash_function, compare_function arguments.
(bcache_full): Ditto.
* bcache.c (bcache): Update prototype.
(bcache_full): Ditto.
* macrotab.c (macro_bcache): Updated.
* symfile.c (allocate_symtab): Updated.
diff --git a/gdb/bcache.c b/gdb/bcache.c
index 7d9180c..bef2596 100644
--- a/gdb/bcache.c
+++ b/gdb/bcache.c
@@ -98,12 +98,19 @@ struct bcache
unsigned long
hash(const void *addr, int length)
{
+ return hash_continue (addr, length, 0);
+}
+
+/* Continue the calculation of the hash H at the given address. */
+
+unsigned long
+hash_continue (const void *addr, int length, unsigned long h)
+{
const unsigned char *k, *e;
- unsigned long h;
k = (const unsigned char *)addr;
e = k+length;
- for (h=0; k< e;++k)
+ for (; k< e;++k)
{
h *=16777619;
h ^= *k;
@@ -194,21 +201,34 @@ expand_hash_table (struct bcache *bcache)
/* Find a copy of the LENGTH bytes at ADDR in BCACHE. If BCACHE has
never seen those bytes before, add a copy of them to BCACHE. In
- either case, return a pointer to BCACHE's copy of that string. */
+ either case, return a pointer to BCACHE's copy of that string.
+ If HASH_FUNCTION and COMPARE_FUNCTION are not NULL they will be
+ used for hash calculation and comparing table elements respectively.
+ Otherwise the hash is calculated using the byte string and a
+ simple byte comparison is performed. */
blank line between a function comment and definition
const void *
-bcache (const void *addr, int length, struct bcache *bcache)
+bcache (const void *addr, int length, struct bcache *bcache,
+ unsigned long (*hash_function)(const void*),
+ int (*compare_function)(const void*, const void*))
{
- return bcache_full (addr, length, bcache, NULL);
+ return bcache_full (addr, length, bcache, NULL, hash_function,
+ compare_function);
}
I think it would be better to attach the hash and compare functions to
the bcache object.
E.g. add hash_function, compare_function parameters to bcache_xmalloc.
/* Find a copy of the LENGTH bytes at ADDR in BCACHE. If BCACHE has
never seen those bytes before, add a copy of them to BCACHE. In
either case, return a pointer to BCACHE's copy of that string. If
optional ADDED is not NULL, return 1 in case of new entry or 0 if
- returning an old entry. */
+ returning an old entry.
+ If HASH_FUNCTION and COMPARE_FUNCTION are not NULL they will be
+ used for hash calculation and comparing table elements respectively.
+ Otherwise the hash is calculated using the byte string and a
+ simple byte comparison is performed. */
const void *
-bcache_full (const void *addr, int length, struct bcache *bcache, int *added)
+bcache_full (const void *addr, int length, struct bcache *bcache, int *added,
+ unsigned long (*hash_function)(const void*),
+ int (*compare_function)(const void*, const void*))
{
unsigned long full_hash;
unsigned short half_hash;
@@ -235,7 +255,11 @@ bcache_full (const void *addr, int length, struct
bcache *bcache, int *added)
bcache->total_count++;
bcache->total_size += length;
- full_hash = hash (addr, length);
+ if (hash_function == NULL)
+ full_hash = hash (addr, length);
+ else
+ full_hash = hash_function (addr);
[for reference sake]
Once hash_function is in struct bcache I'd store a pointer to the
default hasher, instead of having NULL mean "use default hasher".
[see below for compare_function - I wrote that part first]
+
half_hash = (full_hash >> 16);
hash_index = full_hash % bcache->num_buckets;
@@ -246,9 +270,18 @@ bcache_full (const void *addr, int length, struct
bcache *bcache, int *added)
{
if (s->half_hash == half_hash)
{
- if (s->length == length
- && ! memcmp (&s->d.data, addr, length))
- return &s->d.data;
+ if (s->length == length)
+ {
+ int equal = 0;
+
+ if (compare_function == NULL)
+ equal = (memcmp (&s->d.data, addr, length) == 0);
+ else
+ equal = compare_function (&s->d.data, addr);
[for reference sake]
Once compare_function lives in struct bcache, I have a slight
preference for not having compare_function == NULL mean "use memcmp".
Instead store a pointer to memcmp (or wrapper) in the field (and then
you don't have to test for NULL above). It would mean that all
compare_functions would get a length parameter that they may not use
(except perhaps in an assert that the value is the expected size), but
I think that's ok.
A NULL value for compare_function passed to bcache_xmalloc could mean
"use default" though.
+
+ if (equal)
+ return &s->d.data;
+ }
else
bcache->half_hash_miss_count++;
}
diff --git a/gdb/bcache.h b/gdb/bcache.h
index da69a2d..799c744 100644
--- a/gdb/bcache.h
+++ b/gdb/bcache.h
@@ -146,13 +146,17 @@ struct bcache;
Since the cached value is ment to be read-only, return a const
buffer. */
extern const void *bcache (const void *addr, int length,
- struct bcache *bcache);
+ struct bcache *bcache,
+ unsigned long (*hash_function)(const void*),
+ int (*compare_function)(const void*, const void*));
/* Like bcache, but if ADDED is not NULL, set *ADDED to true if the
bytes were newly added to the cache, or to false if the bytes were
found in the cache. */
extern const void *bcache_full (const void *addr, int length,
- struct bcache *bcache, int *added);
+ struct bcache *bcache, int *added,
+ unsigned long (*hash_function)(const void*),
+ int (*compare_function)(const void*, const void*));
/* Free all the storage used by BCACHE. */
extern void bcache_xfree (struct bcache *bcache);
@@ -169,5 +173,6 @@ extern int bcache_memory_used (struct bcache *bcache);
/* The hash function */
extern unsigned long hash(const void *addr, int length);
-
+extern unsigned long hash_continue (const void *addr, int length,
+ unsigned long h);
blank line
#endif /* BCACHE_H */
diff --git a/gdb/macrotab.c b/gdb/macrotab.c
index 93651ab..eb3eef4 100644
--- a/gdb/macrotab.c
+++ b/gdb/macrotab.c
@@ -109,7 +109,7 @@ static const void *
macro_bcache (struct macro_table *t, const void *addr, int len)
{
if (t->bcache)
- return bcache (addr, len, t->bcache);
+ return bcache (addr, len, t->bcache, NULL, NULL);
else
{
void *copy = xmalloc (len);
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index bc47681..f4cdebd 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -1270,6 +1270,47 @@ start_psymtab_common (struct objfile *objfile,
return (psymtab);
}
+/* Calculate a hash code for the given partial symbol. The hash is
+ calculated using the symbol's value, language, domain, class
+ and name. These are the values which are set by
+ add_psymbol_to_bcache. */
+
+static unsigned long
+psymbol_hash (const void *addr)
+{
+ unsigned long h = 0;
+ struct partial_symbol *psymbol = (struct partial_symbol *) addr;
+ unsigned int lang = psymbol->ginfo.language;
+ unsigned int domain = PSYMBOL_DOMAIN (psymbol);
+ unsigned int class = PSYMBOL_CLASS (psymbol);
+
+ h = hash_continue (&psymbol->ginfo.value, sizeof (psymbol->ginfo.value), 0);
s/0/h/
+ h = hash_continue (&lang, sizeof (unsigned int), h);
+ h = hash_continue (&domain, sizeof (unsigned int), h);
+ h = hash_continue (&class, sizeof (unsigned int), h);
+ h = hash_continue (psymbol->ginfo.name, strlen (psymbol->ginfo.name), h);
+
+ return h;
+}
+
+/* Returns true if the symbol at addr1 equals the symbol at addr2.
+ For the comparison this function uses a symbols value,
+ language, domain, class and name. */
+
+static int
+psymbol_compare (const void *addr1, const void *addr2)
+{
+ struct partial_symbol *sym1 = (struct partial_symbol *) addr1;
+ struct partial_symbol *sym2 = (struct partial_symbol *) addr2;
+
+ return (memcmp (&sym1->ginfo.value, &sym1->ginfo.value,
+ sizeof (sym1->ginfo.value)) == 0
+ && sym1->ginfo.language == sym2->ginfo.language
+ && PSYMBOL_DOMAIN (sym1) == PSYMBOL_DOMAIN (sym2)
+ && PSYMBOL_CLASS (sym1) == PSYMBOL_CLASS (sym2)
+ && strcmp (sym1->ginfo.name, sym2->ginfo.name) == 0);
+}
+
/* Helper function, initialises partial symbol structure and stashes
it into objfile's bcache. Note that our caching mechanism will
use all fields of struct partial_symbol to determine hash value of the
@@ -1312,7 +1353,8 @@ add_psymbol_to_bcache (char *name, int
namelength, int copy_name,
/* Stash the partial symbol away in the cache */
return bcache_full (&psymbol, sizeof (struct partial_symbol),
- objfile->psymbol_cache, added);
+ objfile->psymbol_cache, added, psymbol_hash,
+ psymbol_compare);
}
/* Helper function, adds partial symbol to the given partial symbol
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 2cb6b7f..5e7b7c2 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2729,7 +2729,7 @@ allocate_symtab (char *filename, struct objfile *objfile)
obstack_alloc (&objfile->objfile_obstack, sizeof (struct symtab));
memset (symtab, 0, sizeof (*symtab));
symtab->filename = (char *) bcache (filename, strlen (filename) + 1,
- objfile->filename_cache);
+ objfile->filename_cache, NULL, NULL);
symtab->fullname = NULL;
symtab->language = deduce_language_from_filename (filename);
symtab->debugformat = "unknown";
next prev parent reply other threads:[~2010-08-16 18:29 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-08-16 14:11 sami wagiaalla
2010-08-16 18:29 ` Doug Evans [this message]
2010-08-16 18:56 ` Doug Evans
2010-08-16 19:56 ` sami wagiaalla
2010-08-19 16:32 ` [patch 1/2] Use custom hash function with bcache [Re: [RFC] Use custom hash function with bcache] sami wagiaalla
2010-08-19 20:26 ` Tom Tromey
2010-08-25 18:30 ` sami wagiaalla
2010-08-30 20:53 ` Tom Tromey
2010-09-01 8:25 ` Regression for gdb.stabs/gdb11479.exp [Re: [patch 1/2] " Jan Kratochvil
2010-09-01 16:20 ` Joel Brobecker
2010-09-01 16:47 ` Joel Brobecker
2010-09-01 17:03 ` sami wagiaalla
2010-09-01 17:17 ` Joel Brobecker
2010-09-01 18:09 ` sami wagiaalla
2010-09-01 18:19 ` Jan Kratochvil
2010-09-01 18:24 ` Doug Evans
2010-09-01 18:38 ` Tom Tromey
2010-09-01 19:01 ` sami wagiaalla
2010-09-01 19:15 ` Doug Evans
2010-09-01 19:17 ` Doug Evans
2010-09-01 19:59 ` sami wagiaalla
2010-09-01 23:16 ` Doug Evans
2010-09-01 23:11 ` Doug Evans
2010-09-01 23:19 ` Doug Evans
2010-09-01 23:19 ` Doug Evans
2010-09-02 15:43 ` sami wagiaalla
2010-09-02 20:25 ` Doug Evans
2010-09-03 15:59 ` Doug Evans
2010-09-04 14:29 ` sami wagiaalla
2010-09-06 9:46 ` Daniel Jacobowitz
2010-08-16 19:14 ` [RFC] Use custom hash function with bcache Daniel Jacobowitz
2010-08-16 19:50 ` sami wagiaalla
2010-08-16 20:04 ` Daniel Jacobowitz
2010-08-16 20:11 ` sami wagiaalla
2010-08-16 20:49 ` Daniel Jacobowitz
2010-08-17 17:02 ` sami wagiaalla
2010-08-17 17:40 ` Daniel Jacobowitz
2010-08-17 23:26 ` Tom Tromey
2010-08-18 15:13 ` sami wagiaalla
2010-08-18 15:24 ` Tom Tromey
2010-08-19 16:33 ` sami wagiaalla
2010-08-19 16:37 ` [patch 2/2] Use custom hash function with bcache [Re: [RFC] Use custom hash function with bcache] sami wagiaalla
2010-08-19 20:32 ` [RFC] Use custom hash function with bcache Tom Tromey
2010-08-25 18:32 ` [patch 2/2] Use custom hash function with bcache [Re: [RFC] Use custom hash function with bcache] sami wagiaalla
2010-08-30 20:58 ` Tom Tromey
2010-08-30 21:13 ` Tom Tromey
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=AANLkTikH1rBzysO-nNT-w3a0me7zMcGfSpn7+7oJQdWk@mail.gmail.com \
--to=dje@google.com \
--cc=gdb-patches@sourceware.org \
--cc=swagiaal@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox