gdb/
[binutils-gdb.git] / gdb / bcache.c
index 945453787e297ff87aca593e2d2bd68e5bc3f8ce..7d9180cbec3c36ca56dc2bf5276049d569979a22 100644 (file)
@@ -2,7 +2,7 @@
    Written by Fred Fish <fnf@cygnus.com>
    Rewritten by Jim Blandy <jimb@cygnus.com>
 
-   Copyright (C) 1999, 2000, 2002, 2003, 2007, 2008
+   Copyright (C) 1999, 2000, 2002, 2003, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -98,17 +98,17 @@ struct bcache
 unsigned long
 hash(const void *addr, int length)
 {
-               const unsigned char *k, *e;
-               unsigned long h;
-               
-               k = (const unsigned char *)addr;
-               e = k+length;
-               for (h=0; k< e;++k)
-               {
-                               h *=16777619;
-                               h ^= *k;
-               }
-               return (h);
+  const unsigned char *k, *e;
+  unsigned long h;
+
+  k = (const unsigned char *)addr;
+  e = k+length;
+  for (h=0; k< e;++k)
+    {
+      h *=16777619;
+      h ^= *k;
+    }
+  return (h);
 }
 \f
 /* Growing the bcache's hash table.  */
@@ -152,6 +152,7 @@ expand_hash_table (struct bcache *bcache)
   /* Allocate the new table.  */
   {
     size_t new_size = new_num_buckets * sizeof (new_buckets[0]);
+
     new_buckets = (struct bstring **) xmalloc (new_size);
     memset (new_buckets, 0, new_size);
 
@@ -194,14 +195,39 @@ 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.  */
-static void *
-bcache_data (const void *addr, int length, struct bcache *bcache)
+const void *
+bcache (const void *addr, int length, struct bcache *bcache)
+{
+  return bcache_full (addr, length, bcache, NULL);
+}
+
+/* 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.  */
+
+const void *
+bcache_full (const void *addr, int length, struct bcache *bcache, int *added)
 {
   unsigned long full_hash;
   unsigned short half_hash;
   int hash_index;
   struct bstring *s;
 
+  if (added)
+    *added = 0;
+
+  /* Lazily initialize the obstack.  This can save quite a bit of
+     memory in some cases.  */
+  if (bcache->total_count == 0)
+    {
+      /* We could use obstack_specify_allocation here instead, but
+        gdb_obstack.h specifies the allocation/deallocation
+        functions.  */
+      obstack_init (&bcache->cache);
+    }
+
   /* If our average chain length is too high, expand the hash table.  */
   if (bcache->unique_count >= bcache->num_buckets * CHAIN_LENGTH_THRESHOLD)
     expand_hash_table (bcache);
@@ -232,6 +258,7 @@ bcache_data (const void *addr, int length, struct bcache *bcache)
   {
     struct bstring *new
       = obstack_alloc (&bcache->cache, BSTRING_SIZE (length));
+
     memcpy (&new->d.data, addr, length);
     new->length = length;
     new->next = bcache->bucket[hash_index];
@@ -242,21 +269,12 @@ bcache_data (const void *addr, int length, struct bcache *bcache)
     bcache->unique_size += length;
     bcache->structure_size += BSTRING_SIZE (length);
 
+    if (added)
+      *added = 1;
+
     return &new->d.data;
   }
 }
-
-void *
-deprecated_bcache (const void *addr, int length, struct bcache *bcache)
-{
-  return bcache_data (addr, length, bcache);
-}
-
-const void *
-bcache (const void *addr, int length, struct bcache *bcache)
-{
-  return bcache_data (addr, length, bcache);
-}
 \f
 /* Allocating and freeing bcaches.  */
 
@@ -265,10 +283,7 @@ bcache_xmalloc (void)
 {
   /* Allocate the bcache pre-zeroed.  */
   struct bcache *b = XCALLOC (1, struct bcache);
-  /* We could use obstack_specify_allocation here instead, but
-     gdb_obstack.h specifies the allocation/deallocation
-     functions.  */
-  obstack_init (&b->cache);
+
   return b;
 }
 
@@ -278,7 +293,9 @@ bcache_xfree (struct bcache *bcache)
 {
   if (bcache == NULL)
     return;
-  obstack_free (&bcache->cache, 0);
+  /* Only free the obstack if we actually initialized it.  */
+  if (bcache->total_count > 0)
+    obstack_free (&bcache->cache, 0);
   xfree (bcache->bucket);
   xfree (bcache);
 }
@@ -287,15 +304,6 @@ bcache_xfree (struct bcache *bcache)
 \f
 /* Printing statistics.  */
 
-static int
-compare_ints (const void *ap, const void *bp)
-{
-  /* Because we know we're comparing two ints which are positive,
-     there's no danger of overflow here.  */
-  return * (int *) ap - * (int *) bp;
-}
-
-
 static void
 print_percentage (int portion, int total)
 {
@@ -353,9 +361,9 @@ print_bcache_statistics (struct bcache *c, char *type)
 
     /* To compute the median, we need the set of chain lengths sorted.  */
     qsort (chain_length, c->num_buckets, sizeof (chain_length[0]),
-          compare_ints);
+          compare_positive_ints);
     qsort (entry_size, c->unique_count, sizeof (entry_size[0]),
-          compare_ints);
+          compare_positive_ints);
 
     if (c->num_buckets > 0)
       {
@@ -437,5 +445,7 @@ print_bcache_statistics (struct bcache *c, char *type)
 int
 bcache_memory_used (struct bcache *bcache)
 {
+  if (bcache->total_count == 0)
+    return 0;
   return obstack_memory_used (&bcache->cache);
 }