]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Support pool of unique string in pub_tool_deduppoolalloc.h
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Fri, 11 Nov 2016 13:30:08 +0000 (13:30 +0000)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Fri, 11 Nov 2016 13:30:08 +0000 (13:30 +0000)
This is support code for the xtree implementation.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@16120

coregrind/m_deduppoolalloc.c
include/pub_tool_deduppoolalloc.h

index f7ebd27183c4e2befe1bce80820d1d56bf770b53..b8f10c72d60ba1a824200513a3aaa8791226d9ec 100644 (file)
@@ -41,6 +41,7 @@
 struct _DedupPoolAlloc {
    SizeT  poolSzB; /* Minimum size of a pool. */
    SizeT  fixedSzb; /* If using VG_(allocFixedEltDedupPA), size of elements */
+   Bool   strPA;    /* True if this is a string dedup pool */
    SizeT  eltAlign;
    void*   (*alloc_fn)(const HChar*, SizeT); /* pool allocator */
    const HChar*  cc; /* pool allocator's cost centre */
@@ -75,7 +76,8 @@ typedef
    struct _ht_node {
       struct _ht_node *next; // Read/Write by hashtable (pub_tool_hashtable.h)
       UWord   key;           // Read by hashtable (pub_tool_hashtable.h)
-      SizeT   eltSzB;
+      SizeT   eltSzBorStrNr; // for a normal pool, elt size 
+                             // for a string pool, the unique str number
       const void *elt;
    }
    ht_node;
@@ -97,6 +99,7 @@ DedupPoolAlloc* VG_(newDedupPA) ( SizeT  poolSzB,
    VG_(memset)(ddpa, 0, sizeof(*ddpa));
    ddpa->poolSzB  = poolSzB;
    ddpa->fixedSzb = 0;
+   ddpa->strPA = False;
    ddpa->eltAlign = eltAlign;
    ddpa->alloc_fn = alloc_fn;
    ddpa->cc       = cc;
@@ -189,14 +192,24 @@ static Word cmp_pool_elt (const void* node1, const void* node2 )
    /* As this function is called by hashtable, that has already checked
       for key equality, it is likely that it is the 'good' element.
       So, we handle the equal case first. */
-   if (hnode1->eltSzB == hnode2->eltSzB)
-      return VG_(memcmp) (hnode1->elt, hnode2->elt, hnode1->eltSzB);
-   else if (hnode1->eltSzB < hnode2->eltSzB)
+   if (hnode1->eltSzBorStrNr == hnode2->eltSzBorStrNr)
+      return VG_(memcmp) (hnode1->elt, hnode2->elt, hnode1->eltSzBorStrNr);
+   else if (hnode1->eltSzBorStrNr < hnode2->eltSzBorStrNr)
       return -1;
    else
       return 1;
 }
 
+/* String compare function for 'gen' hash table.
+   Similarly to cmp_pool_elt, no need to compare the key. */
+static Word cmp_pool_str (const void* node1, const void* node2 )
+{
+   const ht_node* hnode1 = node1;
+   const ht_node* hnode2 = node2;
+
+   return VG_(strcmp)(hnode1->elt, hnode2->elt);
+}
+
 /* Print some stats. */
 static void print_stats (DedupPoolAlloc *ddpa)
 {
@@ -209,7 +222,10 @@ static void print_stats (DedupPoolAlloc *ddpa)
                 VG_(sizeXA)(ddpa->pools),
                 ddpa->curpool ?
                 (long int) (ddpa->curpool_limit - ddpa->curpool_free + 1) : 0);
-   VG_(HT_print_stats) (ddpa->ht_elements, cmp_pool_elt);
+   if (ddpa->strPA)
+      VG_(HT_print_stats) (ddpa->ht_elements, cmp_pool_str);
+   else
+      VG_(HT_print_stats) (ddpa->ht_elements, cmp_pool_elt);
 }
 
 /* Dummy free, as the ht elements are allocated in a pool, and
@@ -247,8 +263,8 @@ static UInt sdbm_hash (const UChar* buf, UInt len )
   return h;
 }
 
-const void* VG_(allocEltDedupPA) (DedupPoolAlloc *ddpa, SizeT eltSzB,
-                                  const void *elt)
+static ht_node* allocEltDedupPA (DedupPoolAlloc *ddpa, SizeT eltSzB,
+                                 const void *elt)
 {
    ht_node ht_elt;
    void* elt_ins;
@@ -260,12 +276,16 @@ const void* VG_(allocEltDedupPA) (DedupPoolAlloc *ddpa, SizeT eltSzB,
 
    ht_elt.key = sdbm_hash (elt, eltSzB);
 
-   ht_elt.eltSzB = eltSzB;
    ht_elt.elt = elt;
 
-   ht_ins = VG_(HT_gen_lookup) (ddpa->ht_elements, &ht_elt, cmp_pool_elt);
+   if (ddpa->strPA)
+      ht_ins = VG_(HT_gen_lookup) (ddpa->ht_elements, &ht_elt, cmp_pool_str);
+   else {
+      ht_elt.eltSzBorStrNr = eltSzB;
+      ht_ins = VG_(HT_gen_lookup) (ddpa->ht_elements, &ht_elt, cmp_pool_elt);
+   }
    if (ht_ins)
-      return ht_ins->elt;
+      return ht_ins;
 
    /* Not found -> we need to allocate a new element from the pool
       and insert it in the hash table of inserted elements. */
@@ -291,10 +311,37 @@ const void* VG_(allocEltDedupPA) (DedupPoolAlloc *ddpa, SizeT eltSzB,
    VG_(memcpy)(elt_ins, elt, eltSzB);
    ht_ins = VG_(allocEltPA) (ddpa->ht_node_pa);
    ht_ins->key = ht_elt.key;
-   ht_ins->eltSzB = eltSzB;
+   if (ddpa->strPA)
+      ht_ins->eltSzBorStrNr = VG_(HT_count_nodes)(ddpa->ht_elements) + 1;
+   else
+      ht_ins->eltSzBorStrNr = eltSzB;
    ht_ins->elt = elt_ins;
    VG_(HT_add_node)(ddpa->ht_elements, ht_ins);
-   return elt_ins;
+   return ht_ins;
+}
+
+const void* VG_(allocEltDedupPA) (DedupPoolAlloc *ddpa, SizeT eltSzB,
+                                  const void *elt)
+{
+   return allocEltDedupPA(ddpa, eltSzB, elt)->elt;
+}
+
+UInt VG_(allocStrDedupPA) (DedupPoolAlloc *ddpa,
+                           const HChar* str,
+                           Bool* newStr)
+{
+   if (!ddpa->strPA) {
+      // First insertion in this ddpa
+      vg_assert (ddpa->nr_alloc_calls == 0);
+      vg_assert (ddpa->fixedSzb == 0);
+      ddpa->strPA = True;
+   }
+
+   const UInt nr_str = VG_(HT_count_nodes)(ddpa->ht_elements);
+   const ht_node* ht_ins = allocEltDedupPA(ddpa, VG_(strlen)(str)+1, str);
+
+   *newStr = nr_str < VG_(HT_count_nodes)(ddpa->ht_elements);
+   return ht_ins->eltSzBorStrNr;
 }
 
 static __inline__
@@ -311,6 +358,7 @@ UInt VG_(allocFixedEltDedupPA) (DedupPoolAlloc *ddpa,
 {
    if (ddpa->fixedSzb == 0) {
       // First insertion in this ddpa
+      vg_assert (!ddpa->strPA);
       vg_assert (ddpa->nr_alloc_calls == 0);
       vg_assert (eltSzB > 0);
       ddpa->fixedSzb = eltSzB;
index a4c1a098cd9517811bca3a8cbe0698bb0b4f7e61..969c42cc989e10fd4351d024aa50462918312949 100644 (file)
@@ -44,8 +44,8 @@
 // individually.
 // Once allocated, an element must not be modified anymore.
 //
-// Elements can be inserted in the pool using VG_(allocEltDedupPA)
-// or using VG_(allocFixedEltDedupPA).
+// Elements can be inserted in the pool using VG_(allocEltDedupPA),
+// VG_(allocFixedEltDedupPA) or VG_(allocStrDedupPA).
 //
 // Use VG_(allocFixedEltDedupPA) to allocate elements that are all of
 // the same size and that you want to identify with a (small) number:
 // The address of an element allocated with VG_(allocEltDedupPA) does
 // not change, even if new elements are inserted in the pool.
 //
+// Use VG_(allocStrDedupPA) to create a pool of strings (in other words, a
+//  dictionnary of strings). Similarly to VG_(allocFixedEltDedupPA), strings
+// inserted in a dedup pool can be identified by an element number.
+//
 // In the same pool, you can only use one of the allocate element functions.
 // 
 // A dedup pool allocator has significantly less memory overhead than
@@ -93,29 +97,42 @@ extern DedupPoolAlloc* VG_(newDedupPA) ( SizeT  poolSzB,
                                          const  HChar* cc,
                                          void   (*free_fn)(void*) );
 
-/* Allocates a new element from ddpa with eltSzB bytes to store elt.
+/* Allocates or retrieve element from ddpa with eltSzB bytes to store elt.
    This function never returns NULL.
    If ddpa already contains an element equal to elt, then the address of
    the already existing element is returned.
    Equality between elements is done by comparing all bytes.
    So, if void *elt points to a struct, be sure to initialise all components
    and the holes between components. */
-extern const void* VG_(allocEltDedupPA) (DedupPoolAlloc *ddpa,
-                                         SizeT eltSzB, const void *elt);
+extern const void* VG_(allocEltDedupPA) (DedupPoolAllocddpa,
+                                         SizeT eltSzB, const voidelt);
 
-/* Allocates a new (fixed size) element from ddpa. Returns the
-   unique number identifying this element. This function never returns NULL.
+/* Allocates or retrieve a (fixed size) element from ddpa. Returns the
+   unique number identifying this element.
    Similarly to VG_(allocEltDedupPA), this will return the unique number
    of an already existing identical element to elt. */
-extern UInt VG_(allocFixedEltDedupPA) (DedupPoolAlloc *ddpa,
-                                       SizeT eltSzB, const void *elt);
+extern UInt VG_(allocFixedEltDedupPA) (DedupPoolAllocddpa,
+                                       SizeT eltSzB, const voidelt);
 
 /* Translate an element number to its address. Note that the address
    corresponding to eltNr can change if new elements are inserted
    in the pool. */
-extern void* VG_(indexEltNumber) (DedupPoolAlloc *ddpa,
+extern void* VG_(indexEltNumber) (DedupPoolAllocddpa,
                                   UInt eltNr);
 
+/* Allocates or retrieve a string element from ddpa. Returns the
+   unique number identifying this string.
+   newStr is set to True if the str is a newly inserted string, False
+   if the str was already present in the pool.
+   Similarly to VG_(allocEltDedupPA), this will return the unique number
+   of an already existing identical string. */
+extern UInt VG_(allocStrDedupPA) (DedupPoolAlloc *ddpa,
+                                  const HChar* str,
+                                  Bool* newStr);
+/* Note: Implementing a function to return the string value from its strNr
+   implies some overhead, so will be done only if/when needed. */
+
+
 /* The Dedup Pool Allocator must maintain a data structure to avoid
    duplicates as long as new elements can be allocated from the pool.
    Once no new elements will be allocated, this dedup data structure
@@ -123,14 +140,14 @@ extern void* VG_(indexEltNumber) (DedupPoolAlloc *ddpa,
    it is an error to call VG_(allocEltDedupPA) or VG_(allocFixedEltDedupPA).
    If shrink_block is not NULL, the last pool will be shrunk using
    shrink_block. */
-extern void VG_(freezeDedupPA) (DedupPoolAlloc *ddpa,
+extern void VG_(freezeDedupPA) (DedupPoolAllocddpa,
                                 void (*shrink_block)(void*, SizeT));
 
 /* How many (unique) elements are there in this ddpa now? */
-extern UInt VG_(sizeDedupPA) (DedupPoolAlloc *ddpa);
+extern UInt VG_(sizeDedupPA) (DedupPoolAllocddpa);
 
 /* Free all memory associated with a DedupPoolAlloc. */
-extern void VG_(deleteDedupPA) ( DedupPoolAlloc *ddpa);
+extern void VG_(deleteDedupPA) ( DedupPoolAllocddpa);
 
 #endif   // __PUB_TOOL_DEDUPPOOLALLOC_