17293d2530f8c60c1060f9f003e214cc341d35266philippe/*--------------------------------------------------------------------*/
27293d2530f8c60c1060f9f003e214cc341d35266philippe/*--- A pool (memory) allocator that avoids duplicated copies.     ---*/
37293d2530f8c60c1060f9f003e214cc341d35266philippe/*---                                           m_deduppoolalloc.c ---*/
47293d2530f8c60c1060f9f003e214cc341d35266philippe/*--------------------------------------------------------------------*/
57293d2530f8c60c1060f9f003e214cc341d35266philippe/*
67293d2530f8c60c1060f9f003e214cc341d35266philippe   This file is part of Valgrind, a dynamic binary instrumentation
77293d2530f8c60c1060f9f003e214cc341d35266philippe   framework.
87293d2530f8c60c1060f9f003e214cc341d35266philippe
9b3a1e4bffbdbbf38304f216af405009868f43628sewardj   Copyright (C) 2014-2015 Philippe Waroquiers philippe.waroquiers@skynet.be
107293d2530f8c60c1060f9f003e214cc341d35266philippe
117293d2530f8c60c1060f9f003e214cc341d35266philippe   This program is free software; you can redistribute it and/or
127293d2530f8c60c1060f9f003e214cc341d35266philippe   modify it under the terms of the GNU General Public License as
137293d2530f8c60c1060f9f003e214cc341d35266philippe   published by the Free Software Foundation; either version 2 of the
147293d2530f8c60c1060f9f003e214cc341d35266philippe   License, or (at your option) any later version.
157293d2530f8c60c1060f9f003e214cc341d35266philippe
167293d2530f8c60c1060f9f003e214cc341d35266philippe   This program is distributed in the hope that it will be useful, but
177293d2530f8c60c1060f9f003e214cc341d35266philippe   WITHOUT ANY WARRANTY; without even the implied warranty of
187293d2530f8c60c1060f9f003e214cc341d35266philippe   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
197293d2530f8c60c1060f9f003e214cc341d35266philippe   General Public License for more details.
207293d2530f8c60c1060f9f003e214cc341d35266philippe
217293d2530f8c60c1060f9f003e214cc341d35266philippe   You should have received a copy of the GNU General Public License
227293d2530f8c60c1060f9f003e214cc341d35266philippe   along with this program; if not, write to the Free Software
237293d2530f8c60c1060f9f003e214cc341d35266philippe   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
247293d2530f8c60c1060f9f003e214cc341d35266philippe   02111-1307, USA.
257293d2530f8c60c1060f9f003e214cc341d35266philippe
267293d2530f8c60c1060f9f003e214cc341d35266philippe   The GNU General Public License is contained in the file COPYING.
277293d2530f8c60c1060f9f003e214cc341d35266philippe*/
287293d2530f8c60c1060f9f003e214cc341d35266philippe
297293d2530f8c60c1060f9f003e214cc341d35266philippe#include "pub_core_basics.h"
307293d2530f8c60c1060f9f003e214cc341d35266philippe#include "pub_core_libcbase.h"
317293d2530f8c60c1060f9f003e214cc341d35266philippe#include "pub_core_libcprint.h"
327293d2530f8c60c1060f9f003e214cc341d35266philippe#include "pub_core_libcassert.h"
337293d2530f8c60c1060f9f003e214cc341d35266philippe#include "pub_core_xarray.h"
347293d2530f8c60c1060f9f003e214cc341d35266philippe#include "pub_core_deduppoolalloc.h" /* self */
357293d2530f8c60c1060f9f003e214cc341d35266philippe#include "pub_core_hashtable.h"
367293d2530f8c60c1060f9f003e214cc341d35266philippe#include "pub_core_poolalloc.h"
377293d2530f8c60c1060f9f003e214cc341d35266philippe#include "pub_core_options.h"
387293d2530f8c60c1060f9f003e214cc341d35266philippe#include "pub_core_mallocfree.h"
397293d2530f8c60c1060f9f003e214cc341d35266philippe#include "pub_core_debuglog.h"
407293d2530f8c60c1060f9f003e214cc341d35266philippe
417293d2530f8c60c1060f9f003e214cc341d35266philippestruct _DedupPoolAlloc {
427293d2530f8c60c1060f9f003e214cc341d35266philippe   SizeT  poolSzB; /* Minimum size of a pool. */
431554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   SizeT  fixedSzb; /* If using VG_(allocFixedEltDedupPA), size of elements */
447293d2530f8c60c1060f9f003e214cc341d35266philippe   SizeT  eltAlign;
455e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian   void*   (*alloc_fn)(const HChar*, SizeT); /* pool allocator */
465e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian   const HChar*  cc; /* pool allocator's cost centre */
475e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian   void    (*free_fn)(void*); /* pool allocator's deallocation function */
487293d2530f8c60c1060f9f003e214cc341d35266philippe   /* XArray of void* (pointers to pools).  The pools themselves.
491554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      Each element is a pointer to a block of size at least PoolSzB bytes.
501554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      The last block might be smaller due to a call to shrink_block. */
517293d2530f8c60c1060f9f003e214cc341d35266philippe   XArray *pools;
527293d2530f8c60c1060f9f003e214cc341d35266philippe
537293d2530f8c60c1060f9f003e214cc341d35266philippe   /* hash table of pool elements, used to dedup.
547293d2530f8c60c1060f9f003e214cc341d35266philippe      If NULL, it means the DedupPoolAlloc is frozen. */
5509a4c794458cdb9dea743fa40e450150a2725257florian   VgHashTable *ht_elements;
567293d2530f8c60c1060f9f003e214cc341d35266philippe
577293d2530f8c60c1060f9f003e214cc341d35266philippe   /* Hash table nodes of pool_elements are allocated with a pool, to
587293d2530f8c60c1060f9f003e214cc341d35266philippe      decrease memory overhead during insertion in the DedupPoolAlloc. */
597293d2530f8c60c1060f9f003e214cc341d35266philippe   PoolAlloc *ht_node_pa;
607293d2530f8c60c1060f9f003e214cc341d35266philippe
611554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   UChar *curpool;       /* last allocated pool. */
621554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   UChar *curpool_free;  /* Pos in current pool to allocate next elt.
631554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe                            always aligned on eltAlign. */
647293d2530f8c60c1060f9f003e214cc341d35266philippe   UChar *curpool_limit; /* Last pos in current pool. */
651554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   /* Note that for a fixed size pool, we only have a single pool to allow
661554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      simple/fast indexing. This single pool is grown, which might change
671554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      the address of the already allocated elements. */
687293d2530f8c60c1060f9f003e214cc341d35266philippe
697293d2530f8c60c1060f9f003e214cc341d35266philippe   /* Total nr of alloc calls, resulting in (we hope) a lot less
707293d2530f8c60c1060f9f003e214cc341d35266philippe      real (dedup) elements. */
711554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   ULong nr_alloc_calls;
727293d2530f8c60c1060f9f003e214cc341d35266philippe};
737293d2530f8c60c1060f9f003e214cc341d35266philippe
747293d2530f8c60c1060f9f003e214cc341d35266philippetypedef
757293d2530f8c60c1060f9f003e214cc341d35266philippe   struct _ht_node {
767293d2530f8c60c1060f9f003e214cc341d35266philippe      struct _ht_node *next; // Read/Write by hashtable (pub_tool_hashtable.h)
777293d2530f8c60c1060f9f003e214cc341d35266philippe      UWord   key;           // Read by hashtable (pub_tool_hashtable.h)
787293d2530f8c60c1060f9f003e214cc341d35266philippe      SizeT   eltSzB;
791ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian      const void *elt;
807293d2530f8c60c1060f9f003e214cc341d35266philippe   }
817293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_node;
827293d2530f8c60c1060f9f003e214cc341d35266philippe
835e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorianDedupPoolAlloc* VG_(newDedupPA) ( SizeT  poolSzB,
845e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian                                  SizeT  eltAlign,
855e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian                                  void*  (*alloc_fn)(const HChar*, SizeT),
865e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian                                  const  HChar* cc,
875e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian                                  void   (*free_fn)(void*) )
887293d2530f8c60c1060f9f003e214cc341d35266philippe{
897293d2530f8c60c1060f9f003e214cc341d35266philippe   DedupPoolAlloc* ddpa;
907293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(poolSzB >= eltAlign);
917293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(poolSzB >= 100); /* let's say */
927293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(poolSzB >= 10*eltAlign); /* let's say */
935e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian   vg_assert(alloc_fn);
947293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(cc);
957293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(free_fn);
965e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian   ddpa = alloc_fn(cc, sizeof(*ddpa));
977293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(memset)(ddpa, 0, sizeof(*ddpa));
987293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->poolSzB  = poolSzB;
991554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   ddpa->fixedSzb = 0;
1007293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->eltAlign = eltAlign;
1015e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian   ddpa->alloc_fn = alloc_fn;
1027293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->cc       = cc;
1035e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian   ddpa->free_fn  = free_fn;
1045e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian   ddpa->pools    = VG_(newXA)( alloc_fn, cc, free_fn, sizeof(void*) );
1057293d2530f8c60c1060f9f003e214cc341d35266philippe
1067293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->ht_elements = VG_(HT_construct) (cc);
1077293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->ht_node_pa = VG_(newPA) ( sizeof(ht_node),
1087293d2530f8c60c1060f9f003e214cc341d35266philippe                                   1000,
1095e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian                                   alloc_fn,
1107293d2530f8c60c1060f9f003e214cc341d35266philippe                                   cc,
1117293d2530f8c60c1060f9f003e214cc341d35266philippe                                   free_fn);
1121554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   ddpa->curpool = NULL;
1137293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->curpool_limit = NULL;
114a75b56e924f4679686572b2c4ac5345882d65c6bphilippe   ddpa->curpool_free = NULL;
11591ed8ccd3dae8a6abfaa45cc0d250df47b45187fflorian
1167293d2530f8c60c1060f9f003e214cc341d35266philippe   return ddpa;
1177293d2530f8c60c1060f9f003e214cc341d35266philippe}
1187293d2530f8c60c1060f9f003e214cc341d35266philippe
1197293d2530f8c60c1060f9f003e214cc341d35266philippevoid VG_(deleteDedupPA) ( DedupPoolAlloc* ddpa)
1207293d2530f8c60c1060f9f003e214cc341d35266philippe{
1217293d2530f8c60c1060f9f003e214cc341d35266philippe   Word i;
1227293d2530f8c60c1060f9f003e214cc341d35266philippe   if (ddpa->ht_elements)
1231554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      // Free data structures used for insertion.
1241554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      VG_(freezeDedupPA) (ddpa, NULL);
1257293d2530f8c60c1060f9f003e214cc341d35266philippe   for (i = 0; i < VG_(sizeXA) (ddpa->pools); i++)
1265e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian      ddpa->free_fn (*(UWord **)VG_(indexXA) ( ddpa->pools, i ));
1277293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(deleteXA) (ddpa->pools);
1285e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian   ddpa->free_fn (ddpa);
1297293d2530f8c60c1060f9f003e214cc341d35266philippe}
1307293d2530f8c60c1060f9f003e214cc341d35266philippe
1317293d2530f8c60c1060f9f003e214cc341d35266philippestatic __inline__
1321554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippeUChar* ddpa_align ( DedupPoolAlloc* ddpa, UChar *c )
1337293d2530f8c60c1060f9f003e214cc341d35266philippe{
1341554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   return (UChar*)VG_ROUNDUP(c, ddpa->eltAlign);
1357293d2530f8c60c1060f9f003e214cc341d35266philippe}
1367293d2530f8c60c1060f9f003e214cc341d35266philippe
1371554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe/* Allocate a new pool or grow the (only) pool for a fixed size ddpa. */
1387293d2530f8c60c1060f9f003e214cc341d35266philippe__attribute__((noinline))
139e3e515b85bce2fdfadabac0a566bbc4a3a2178fephilippestatic void ddpa_add_new_pool_or_grow ( DedupPoolAlloc* ddpa )
1407293d2530f8c60c1060f9f003e214cc341d35266philippe{
1417293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(ddpa);
1421554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe
1431554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   if (ddpa->fixedSzb > 0 && ddpa->curpool != NULL) {
1441554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      // Grow (* 2) the current (fixed elt) pool
1451554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      UChar *curpool_align = ddpa_align(ddpa, ddpa->curpool);
1461554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      SizeT curpool_used = ddpa->curpool_free - curpool_align;
1471554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      SizeT curpool_size = ddpa->curpool_limit - ddpa->curpool + 1;
1485e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian      UChar *newpool = ddpa->alloc_fn (ddpa->cc, 2 * curpool_size);
1491554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      UChar *newpool_free = ddpa_align (ddpa, newpool);
1501554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      UChar *newpool_limit = newpool + 2 * curpool_size - 1;
151e3e515b85bce2fdfadabac0a566bbc4a3a2178fephilippe      Word reloc_offset = (Addr)newpool_free - (Addr)curpool_align;
152e3e515b85bce2fdfadabac0a566bbc4a3a2178fephilippe      ht_node *n;
1531554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe
1541554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      VG_(memcpy) (newpool_free, curpool_align, curpool_used);
155e3e515b85bce2fdfadabac0a566bbc4a3a2178fephilippe      /* We have reallocated the (only) pool. We need to relocate the pointers
156e3e515b85bce2fdfadabac0a566bbc4a3a2178fephilippe         in the hash table nodes. */
157e3e515b85bce2fdfadabac0a566bbc4a3a2178fephilippe      VG_(HT_ResetIter) (ddpa->ht_elements);
158e3e515b85bce2fdfadabac0a566bbc4a3a2178fephilippe      while ((n = VG_(HT_Next) (ddpa->ht_elements))) {
159e3e515b85bce2fdfadabac0a566bbc4a3a2178fephilippe        n->elt = (void*)((Addr)n->elt + reloc_offset);
160e3e515b85bce2fdfadabac0a566bbc4a3a2178fephilippe      }
1611554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      newpool_free += curpool_used;
1621554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe
1631554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      VG_(dropHeadXA) (ddpa->pools, 1);
1645e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian      ddpa->free_fn (ddpa->curpool);
1651554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      ddpa->curpool = newpool;
1661554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      ddpa->curpool_free = newpool_free;
1671554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      ddpa->curpool_limit = newpool_limit;
1681554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      VG_(addToXA)( ddpa->pools, &ddpa->curpool);
1691554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   } else {
1701554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      /* Allocate a new pool, or allocate the first/only pool for a
1711554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe         fixed size ddpa. */
1725e1e9234daf0d106770fe34ee26bfd8c87cc0bdbflorian      ddpa->curpool = ddpa->alloc_fn( ddpa->cc, ddpa->poolSzB);
1731554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      ddpa->curpool_limit = ddpa->curpool + ddpa->poolSzB - 1;
1741554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      ddpa->curpool_free = ddpa_align (ddpa, ddpa->curpool);
1751554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      /* add to our collection of pools */
1761554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      VG_(addToXA)( ddpa->pools, &ddpa->curpool );
1771554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   }
1787293d2530f8c60c1060f9f003e214cc341d35266philippe}
1797293d2530f8c60c1060f9f003e214cc341d35266philippe
180e437427c93a605ac907137b3307f1f63a1462524philippe/* Compare function for 'gen' hash table. No need to compare the key
181e437427c93a605ac907137b3307f1f63a1462524philippe   in this function, as the hash table already does it for us,
182e437427c93a605ac907137b3307f1f63a1462524philippe   and that in any case, if the data is equal, the keys must also be
183e437427c93a605ac907137b3307f1f63a1462524philippe   equal. */
1847293d2530f8c60c1060f9f003e214cc341d35266philippestatic Word cmp_pool_elt (const void* node1, const void* node2 )
1857293d2530f8c60c1060f9f003e214cc341d35266philippe{
1867293d2530f8c60c1060f9f003e214cc341d35266philippe   const ht_node* hnode1 = node1;
1877293d2530f8c60c1060f9f003e214cc341d35266philippe   const ht_node* hnode2 = node2;
1887293d2530f8c60c1060f9f003e214cc341d35266philippe
189e437427c93a605ac907137b3307f1f63a1462524philippe   /* As this function is called by hashtable, that has already checked
190e437427c93a605ac907137b3307f1f63a1462524philippe      for key equality, it is likely that it is the 'good' element.
191e437427c93a605ac907137b3307f1f63a1462524philippe      So, we handle the equal case first. */
192e437427c93a605ac907137b3307f1f63a1462524philippe   if (hnode1->eltSzB == hnode2->eltSzB)
1937293d2530f8c60c1060f9f003e214cc341d35266philippe      return VG_(memcmp) (hnode1->elt, hnode2->elt, hnode1->eltSzB);
1947293d2530f8c60c1060f9f003e214cc341d35266philippe   else if (hnode1->eltSzB < hnode2->eltSzB)
1957293d2530f8c60c1060f9f003e214cc341d35266philippe      return -1;
1967293d2530f8c60c1060f9f003e214cc341d35266philippe   else
1977293d2530f8c60c1060f9f003e214cc341d35266philippe      return 1;
1987293d2530f8c60c1060f9f003e214cc341d35266philippe}
1997293d2530f8c60c1060f9f003e214cc341d35266philippe
2007293d2530f8c60c1060f9f003e214cc341d35266philippe/* Print some stats. */
2017293d2530f8c60c1060f9f003e214cc341d35266philippestatic void print_stats (DedupPoolAlloc *ddpa)
2027293d2530f8c60c1060f9f003e214cc341d35266philippe{
2037293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(message)(Vg_DebugMsg,
204a6a6d9247ac4b1ba7f8dc28000cfcadb8feee85bflorian                "dedupPA:%s %ld allocs (%u uniq)"
2057293d2530f8c60c1060f9f003e214cc341d35266philippe                " %ld pools (%ld bytes free in last pool)\n",
2067293d2530f8c60c1060f9f003e214cc341d35266philippe                ddpa->cc,
2077293d2530f8c60c1060f9f003e214cc341d35266philippe                (long int) ddpa->nr_alloc_calls,
2087293d2530f8c60c1060f9f003e214cc341d35266philippe                VG_(HT_count_nodes)(ddpa->ht_elements),
2097293d2530f8c60c1060f9f003e214cc341d35266philippe                VG_(sizeXA)(ddpa->pools),
210a75b56e924f4679686572b2c4ac5345882d65c6bphilippe                ddpa->curpool ?
211a75b56e924f4679686572b2c4ac5345882d65c6bphilippe                (long int) (ddpa->curpool_limit - ddpa->curpool_free + 1) : 0);
2127293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(HT_print_stats) (ddpa->ht_elements, cmp_pool_elt);
2137293d2530f8c60c1060f9f003e214cc341d35266philippe}
2147293d2530f8c60c1060f9f003e214cc341d35266philippe
2157293d2530f8c60c1060f9f003e214cc341d35266philippe/* Dummy free, as the ht elements are allocated in a pool, and
2167293d2530f8c60c1060f9f003e214cc341d35266philippe   we will destroy the pool in one single operation. */
2177293d2530f8c60c1060f9f003e214cc341d35266philippestatic void htelem_dummyfree(void* ht_elem)
2187293d2530f8c60c1060f9f003e214cc341d35266philippe{
2197293d2530f8c60c1060f9f003e214cc341d35266philippe}
2207293d2530f8c60c1060f9f003e214cc341d35266philippe
2210b9d0646949bd382758763664d3bf2d6115993aephilippevoid VG_(freezeDedupPA) (DedupPoolAlloc *ddpa,
2220b9d0646949bd382758763664d3bf2d6115993aephilippe                         void (*shrink_block)(void*, SizeT))
2237293d2530f8c60c1060f9f003e214cc341d35266philippe{
224e3e515b85bce2fdfadabac0a566bbc4a3a2178fephilippe   if (VG_(clo_stats)
2257293d2530f8c60c1060f9f003e214cc341d35266philippe       && (VG_(clo_verbosity) > 2 || VG_(debugLog_getLevel) () >= 2)) {
2267293d2530f8c60c1060f9f003e214cc341d35266philippe      print_stats(ddpa);
2277293d2530f8c60c1060f9f003e214cc341d35266philippe   }
2281554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   vg_assert (!ddpa->fixedSzb || VG_(sizeXA) (ddpa->pools) == 1);
2291554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   if (shrink_block && ddpa->curpool_limit > ddpa->curpool_free)
2301554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      (*shrink_block)(ddpa->curpool, ddpa->curpool_free - ddpa->curpool);
2317293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(HT_destruct) ( ddpa->ht_elements, htelem_dummyfree);
2327293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->ht_elements = NULL;
2337293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(deletePA) (ddpa->ht_node_pa);
2347293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->ht_node_pa = NULL;
2357293d2530f8c60c1060f9f003e214cc341d35266philippe}
2367293d2530f8c60c1060f9f003e214cc341d35266philippe
237883315ac4b9308db4506078fd6768bd69dbcc821philippe
238883315ac4b9308db4506078fd6768bd69dbcc821philippe// hash function used by gawk and SDBM.
239883315ac4b9308db4506078fd6768bd69dbcc821philippestatic UInt sdbm_hash (const UChar* buf, UInt len )
240883315ac4b9308db4506078fd6768bd69dbcc821philippe{
241883315ac4b9308db4506078fd6768bd69dbcc821philippe  UInt h;
242883315ac4b9308db4506078fd6768bd69dbcc821philippe  UInt i;
243883315ac4b9308db4506078fd6768bd69dbcc821philippe
244883315ac4b9308db4506078fd6768bd69dbcc821philippe  h = 0;
245883315ac4b9308db4506078fd6768bd69dbcc821philippe  for (i = 0; i < len; i++)
246883315ac4b9308db4506078fd6768bd69dbcc821philippe    h = *buf++ + (h<<6) + (h<<16) - h;
247883315ac4b9308db4506078fd6768bd69dbcc821philippe  return h;
248883315ac4b9308db4506078fd6768bd69dbcc821philippe}
249883315ac4b9308db4506078fd6768bd69dbcc821philippe
2501ef70c6f00ab1b50d1936f77037e9923d8ed8c59florianconst void* VG_(allocEltDedupPA) (DedupPoolAlloc *ddpa, SizeT eltSzB,
2511ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian                                  const void *elt)
2527293d2530f8c60c1060f9f003e214cc341d35266philippe{
2537293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_node ht_elt;
2547293d2530f8c60c1060f9f003e214cc341d35266philippe   void* elt_ins;
2557293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_node *ht_ins;
2567293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(ddpa);
2577293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(ddpa->ht_elements);
2587293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert (eltSzB <= ddpa->poolSzB);
2597293d2530f8c60c1060f9f003e214cc341d35266philippe
2607293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->nr_alloc_calls++;
2617293d2530f8c60c1060f9f003e214cc341d35266philippe
262883315ac4b9308db4506078fd6768bd69dbcc821philippe   ht_elt.key = sdbm_hash (elt, eltSzB);
2637293d2530f8c60c1060f9f003e214cc341d35266philippe
2647293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_elt.eltSzB = eltSzB;
2651ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian   ht_elt.elt = elt;
2667293d2530f8c60c1060f9f003e214cc341d35266philippe
2677293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_ins = VG_(HT_gen_lookup) (ddpa->ht_elements, &ht_elt, cmp_pool_elt);
2687293d2530f8c60c1060f9f003e214cc341d35266philippe   if (ht_ins)
2697293d2530f8c60c1060f9f003e214cc341d35266philippe      return ht_ins->elt;
2707293d2530f8c60c1060f9f003e214cc341d35266philippe
2717293d2530f8c60c1060f9f003e214cc341d35266philippe   /* Not found -> we need to allocate a new element from the pool
2727293d2530f8c60c1060f9f003e214cc341d35266philippe      and insert it in the hash table of inserted elements. */
2737293d2530f8c60c1060f9f003e214cc341d35266philippe
2741554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   // Add a new pool or grow pool if not enough space in the current pool
275a75b56e924f4679686572b2c4ac5345882d65c6bphilippe   if (UNLIKELY(ddpa->curpool_free == NULL
276a75b56e924f4679686572b2c4ac5345882d65c6bphilippe                || ddpa->curpool_free + eltSzB - 1 > ddpa->curpool_limit)) {
2771554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      ddpa_add_new_pool_or_grow (ddpa);
2787293d2530f8c60c1060f9f003e214cc341d35266philippe   }
2797293d2530f8c60c1060f9f003e214cc341d35266philippe
2807293d2530f8c60c1060f9f003e214cc341d35266philippe   elt_ins = ddpa->curpool_free;
2817293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(memcpy)(elt_ins, elt, eltSzB);
2821554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   ddpa->curpool_free = ddpa_align(ddpa, ddpa->curpool_free + eltSzB);
2837293d2530f8c60c1060f9f003e214cc341d35266philippe
2847293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_ins = VG_(allocEltPA) (ddpa->ht_node_pa);
2857293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_ins->key = ht_elt.key;
2867293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_ins->eltSzB = eltSzB;
2877293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_ins->elt = elt_ins;
2887293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(HT_add_node)(ddpa->ht_elements, ht_ins);
2897293d2530f8c60c1060f9f003e214cc341d35266philippe   return elt_ins;
2907293d2530f8c60c1060f9f003e214cc341d35266philippe}
2911554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe
2921554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippestatic __inline__
2931554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippeUInt elt2nr (DedupPoolAlloc *ddpa, const void *dedup_elt)
2941554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe{
2958eebf23c35d97489c0d3c8b41dd542e00ae6acbdflorian   vg_assert (dedup_elt >= (const void *)ddpa->curpool
2968eebf23c35d97489c0d3c8b41dd542e00ae6acbdflorian              && dedup_elt < (const void *)ddpa->curpool_free);
2978eebf23c35d97489c0d3c8b41dd542e00ae6acbdflorian   return 1 + ((const UChar*)dedup_elt - (const UChar *)ddpa->curpool)
2981554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      / VG_ROUNDUP(ddpa->fixedSzb, ddpa->eltAlign);
2991554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe}
3001554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe
3011554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippeUInt VG_(allocFixedEltDedupPA) (DedupPoolAlloc *ddpa,
3021554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe                                SizeT eltSzB, const void *elt)
3031554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe{
3041554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   if (ddpa->fixedSzb == 0) {
3051554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      // First insertion in this ddpa
3061554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      vg_assert (ddpa->nr_alloc_calls == 0);
3071554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      vg_assert (eltSzB > 0);
3081554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      ddpa->fixedSzb = eltSzB;
3091554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   }
3101554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   vg_assert (ddpa->fixedSzb == eltSzB);
3111ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian   const void *dedup_elt = VG_(allocEltDedupPA) (ddpa, eltSzB, elt);
3121554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   return elt2nr (ddpa, dedup_elt);
3131554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe}
3141554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe
3151554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippevoid* VG_(indexEltNumber) (DedupPoolAlloc *ddpa,
3161554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe                           UInt eltNr)
3171554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe{
3181554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   void *dedup_elt;
3191554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe
320e3e515b85bce2fdfadabac0a566bbc4a3a2178fephilippe   dedup_elt = ddpa->curpool
3211554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      + (eltNr - 1) * VG_ROUNDUP(ddpa->fixedSzb, ddpa->eltAlign);
3221554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe
323e3e515b85bce2fdfadabac0a566bbc4a3a2178fephilippe   vg_assert ((UChar*)dedup_elt >= ddpa->curpool
3241554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe              && (UChar*)dedup_elt < ddpa->curpool_free);
3251554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe
3261554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   return dedup_elt;
3271554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe}
3281554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe
3291554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippeUInt VG_(sizeDedupPA) (DedupPoolAlloc *ddpa)
3301554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe{
3311554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   if (ddpa->curpool == NULL)
3321554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      return 0;
3331554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe
3341554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   vg_assert (ddpa->fixedSzb);
3351554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe   return (ddpa->curpool_free - ddpa_align(ddpa, ddpa->curpool))
3361554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe      / VG_ROUNDUP(ddpa->fixedSzb, ddpa->eltAlign);
3371554fa55be1fb1a7c6633d11ea8ff95be78a9dc6philippe}
338