m_deduppoolalloc.c revision 7293d2530f8c60c1060f9f003e214cc341d35266
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
97293d2530f8c60c1060f9f003e214cc341d35266philippe   Copyright (C) 2014-2014 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. */
437293d2530f8c60c1060f9f003e214cc341d35266philippe   SizeT  eltAlign;
447293d2530f8c60c1060f9f003e214cc341d35266philippe   void*   (*alloc)(const HChar*, SizeT); /* pool allocator */
457293d2530f8c60c1060f9f003e214cc341d35266philippe   const HChar*  cc; /* pool allocator's cc */
467293d2530f8c60c1060f9f003e214cc341d35266philippe   void    (*free)(void*); /* pool allocator's free-er */
477293d2530f8c60c1060f9f003e214cc341d35266philippe   /* XArray of void* (pointers to pools).  The pools themselves.
487293d2530f8c60c1060f9f003e214cc341d35266philippe      Each element is a pointer to a block of size at least PoolSzB bytes. */
497293d2530f8c60c1060f9f003e214cc341d35266philippe   XArray *pools;
507293d2530f8c60c1060f9f003e214cc341d35266philippe
517293d2530f8c60c1060f9f003e214cc341d35266philippe   /* hash table of pool elements, used to dedup.
527293d2530f8c60c1060f9f003e214cc341d35266philippe      If NULL, it means the DedupPoolAlloc is frozen. */
537293d2530f8c60c1060f9f003e214cc341d35266philippe   VgHashTable ht_elements;
547293d2530f8c60c1060f9f003e214cc341d35266philippe
557293d2530f8c60c1060f9f003e214cc341d35266philippe   /* Hash table nodes of pool_elements are allocated with a pool, to
567293d2530f8c60c1060f9f003e214cc341d35266philippe      decrease memory overhead during insertion in the DedupPoolAlloc. */
577293d2530f8c60c1060f9f003e214cc341d35266philippe   PoolAlloc *ht_node_pa;
587293d2530f8c60c1060f9f003e214cc341d35266philippe
597293d2530f8c60c1060f9f003e214cc341d35266philippe   UChar *curpool_free;  /* Pos in current pool to allocate next elt. */
607293d2530f8c60c1060f9f003e214cc341d35266philippe   UChar *curpool_limit; /* Last pos in current pool. */
617293d2530f8c60c1060f9f003e214cc341d35266philippe
627293d2530f8c60c1060f9f003e214cc341d35266philippe   /* Total nr of alloc calls, resulting in (we hope) a lot less
637293d2530f8c60c1060f9f003e214cc341d35266philippe      real (dedup) elements. */
647293d2530f8c60c1060f9f003e214cc341d35266philippe    ULong nr_alloc_calls;
657293d2530f8c60c1060f9f003e214cc341d35266philippe};
667293d2530f8c60c1060f9f003e214cc341d35266philippe
677293d2530f8c60c1060f9f003e214cc341d35266philippetypedef
687293d2530f8c60c1060f9f003e214cc341d35266philippe   struct _ht_node {
697293d2530f8c60c1060f9f003e214cc341d35266philippe      struct _ht_node *next; // Read/Write by hashtable (pub_tool_hashtable.h)
707293d2530f8c60c1060f9f003e214cc341d35266philippe      UWord   key;           // Read by hashtable (pub_tool_hashtable.h)
717293d2530f8c60c1060f9f003e214cc341d35266philippe      SizeT   eltSzB;
727293d2530f8c60c1060f9f003e214cc341d35266philippe      void    *elt;
737293d2530f8c60c1060f9f003e214cc341d35266philippe   }
747293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_node;
757293d2530f8c60c1060f9f003e214cc341d35266philippe
767293d2530f8c60c1060f9f003e214cc341d35266philippeextern DedupPoolAlloc* VG_(newDedupPA) ( SizeT  poolSzB,
777293d2530f8c60c1060f9f003e214cc341d35266philippe                                         SizeT  eltAlign,
787293d2530f8c60c1060f9f003e214cc341d35266philippe                                         void*  (*alloc)(const HChar*, SizeT),
797293d2530f8c60c1060f9f003e214cc341d35266philippe                                         const  HChar* cc,
807293d2530f8c60c1060f9f003e214cc341d35266philippe                                         void   (*free_fn)(void*) )
817293d2530f8c60c1060f9f003e214cc341d35266philippe{
827293d2530f8c60c1060f9f003e214cc341d35266philippe   DedupPoolAlloc* ddpa;
837293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(poolSzB >= eltAlign);
847293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(poolSzB >= 100); /* let's say */
857293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(poolSzB >= 10*eltAlign); /* let's say */
867293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(alloc);
877293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(cc);
887293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(free_fn);
897293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa = alloc(cc, sizeof(*ddpa));
907293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(ddpa);
917293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(memset)(ddpa, 0, sizeof(*ddpa));
927293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->poolSzB  = poolSzB;
937293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->eltAlign = eltAlign;
947293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->alloc    = alloc;
957293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->cc       = cc;
967293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->free     = free_fn;
977293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->pools    = VG_(newXA)( alloc, cc, free_fn, sizeof(void*) );
987293d2530f8c60c1060f9f003e214cc341d35266philippe
997293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->ht_elements = VG_(HT_construct) (cc);
1007293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->ht_node_pa = VG_(newPA) ( sizeof(ht_node),
1017293d2530f8c60c1060f9f003e214cc341d35266philippe                                   1000,
1027293d2530f8c60c1060f9f003e214cc341d35266philippe                                   alloc,
1037293d2530f8c60c1060f9f003e214cc341d35266philippe                                   cc,
1047293d2530f8c60c1060f9f003e214cc341d35266philippe                                   free_fn);
1057293d2530f8c60c1060f9f003e214cc341d35266philippe
1067293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->curpool_limit = NULL;
1077293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->curpool_free = ddpa->curpool_limit + 1;
1087293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(ddpa->pools);
1097293d2530f8c60c1060f9f003e214cc341d35266philippe   return ddpa;
1107293d2530f8c60c1060f9f003e214cc341d35266philippe}
1117293d2530f8c60c1060f9f003e214cc341d35266philippe
1127293d2530f8c60c1060f9f003e214cc341d35266philippevoid VG_(deleteDedupPA) ( DedupPoolAlloc* ddpa)
1137293d2530f8c60c1060f9f003e214cc341d35266philippe{
1147293d2530f8c60c1060f9f003e214cc341d35266philippe   Word i;
1157293d2530f8c60c1060f9f003e214cc341d35266philippe   if (ddpa->ht_elements)
1167293d2530f8c60c1060f9f003e214cc341d35266philippe      VG_(freezeDedupPA) (ddpa); // Free data structures used for insertion.
1177293d2530f8c60c1060f9f003e214cc341d35266philippe   for (i = 0; i < VG_(sizeXA) (ddpa->pools); i++)
1187293d2530f8c60c1060f9f003e214cc341d35266philippe      ddpa->free (*(UWord **)VG_(indexXA) ( ddpa->pools, i ));
1197293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(deleteXA) (ddpa->pools);
1207293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->free (ddpa);
1217293d2530f8c60c1060f9f003e214cc341d35266philippe}
1227293d2530f8c60c1060f9f003e214cc341d35266philippe
1237293d2530f8c60c1060f9f003e214cc341d35266philippestatic __inline__
1247293d2530f8c60c1060f9f003e214cc341d35266philippevoid ddpa_align_curpool_free ( DedupPoolAlloc* ddpa )
1257293d2530f8c60c1060f9f003e214cc341d35266philippe{
1267293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->curpool_free = (UChar*)VG_ROUNDUP(ddpa->curpool_free, ddpa->eltAlign);
1277293d2530f8c60c1060f9f003e214cc341d35266philippe}
1287293d2530f8c60c1060f9f003e214cc341d35266philippe
1297293d2530f8c60c1060f9f003e214cc341d35266philippe/* No space.  Allocate a new pool. */
1307293d2530f8c60c1060f9f003e214cc341d35266philippe__attribute__((noinline))
1317293d2530f8c60c1060f9f003e214cc341d35266philippestatic void ddpa_add_new_pool ( DedupPoolAlloc* ddpa )
1327293d2530f8c60c1060f9f003e214cc341d35266philippe{
1337293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(ddpa);
1347293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->curpool_free = ddpa->alloc( ddpa->cc, ddpa->poolSzB);
1357293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(ddpa->curpool_free);
1367293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->curpool_limit = ddpa->curpool_free + ddpa->poolSzB - 1;
1377293d2530f8c60c1060f9f003e214cc341d35266philippe   /* add to our collection of pools */
1387293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(addToXA)( ddpa->pools, &ddpa->curpool_free );
1397293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa_align_curpool_free (ddpa);
1407293d2530f8c60c1060f9f003e214cc341d35266philippe}
1417293d2530f8c60c1060f9f003e214cc341d35266philippe
1427293d2530f8c60c1060f9f003e214cc341d35266philippestatic Word cmp_pool_elt (const void* node1, const void* node2 )
1437293d2530f8c60c1060f9f003e214cc341d35266philippe{
1447293d2530f8c60c1060f9f003e214cc341d35266philippe   const ht_node* hnode1 = node1;
1457293d2530f8c60c1060f9f003e214cc341d35266philippe   const ht_node* hnode2 = node2;
1467293d2530f8c60c1060f9f003e214cc341d35266philippe
1477293d2530f8c60c1060f9f003e214cc341d35266philippe   if (hnode1->key < hnode2->key)
1487293d2530f8c60c1060f9f003e214cc341d35266philippe      return -1;
1497293d2530f8c60c1060f9f003e214cc341d35266philippe   else if (hnode1->key > hnode2->key)
1507293d2530f8c60c1060f9f003e214cc341d35266philippe      return 1;
1517293d2530f8c60c1060f9f003e214cc341d35266philippe   else if (hnode1->eltSzB == hnode2->eltSzB)
1527293d2530f8c60c1060f9f003e214cc341d35266philippe      return VG_(memcmp) (hnode1->elt, hnode2->elt, hnode1->eltSzB);
1537293d2530f8c60c1060f9f003e214cc341d35266philippe   else if (hnode1->eltSzB < hnode2->eltSzB)
1547293d2530f8c60c1060f9f003e214cc341d35266philippe      return -1;
1557293d2530f8c60c1060f9f003e214cc341d35266philippe   else
1567293d2530f8c60c1060f9f003e214cc341d35266philippe      return 1;
1577293d2530f8c60c1060f9f003e214cc341d35266philippe}
1587293d2530f8c60c1060f9f003e214cc341d35266philippe
1597293d2530f8c60c1060f9f003e214cc341d35266philippe/* Print some stats. */
1607293d2530f8c60c1060f9f003e214cc341d35266philippestatic void print_stats (DedupPoolAlloc *ddpa)
1617293d2530f8c60c1060f9f003e214cc341d35266philippe{
1627293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(message)(Vg_DebugMsg,
1637293d2530f8c60c1060f9f003e214cc341d35266philippe                "dedupPA:%s %ld allocs (%d uniq)"
1647293d2530f8c60c1060f9f003e214cc341d35266philippe                " %ld pools (%ld bytes free in last pool)\n",
1657293d2530f8c60c1060f9f003e214cc341d35266philippe                ddpa->cc,
1667293d2530f8c60c1060f9f003e214cc341d35266philippe                (long int) ddpa->nr_alloc_calls,
1677293d2530f8c60c1060f9f003e214cc341d35266philippe                VG_(HT_count_nodes)(ddpa->ht_elements),
1687293d2530f8c60c1060f9f003e214cc341d35266philippe                VG_(sizeXA)(ddpa->pools),
1697293d2530f8c60c1060f9f003e214cc341d35266philippe                (long int) (ddpa->curpool_limit - ddpa->curpool_free + 1));
1707293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(HT_print_stats) (ddpa->ht_elements, cmp_pool_elt);
1717293d2530f8c60c1060f9f003e214cc341d35266philippe}
1727293d2530f8c60c1060f9f003e214cc341d35266philippe
1737293d2530f8c60c1060f9f003e214cc341d35266philippe/* Dummy free, as the ht elements are allocated in a pool, and
1747293d2530f8c60c1060f9f003e214cc341d35266philippe   we will destroy the pool in one single operation. */
1757293d2530f8c60c1060f9f003e214cc341d35266philippestatic void htelem_dummyfree(void* ht_elem)
1767293d2530f8c60c1060f9f003e214cc341d35266philippe{
1777293d2530f8c60c1060f9f003e214cc341d35266philippe}
1787293d2530f8c60c1060f9f003e214cc341d35266philippe
1797293d2530f8c60c1060f9f003e214cc341d35266philippevoid VG_(freezeDedupPA) (DedupPoolAlloc *ddpa)
1807293d2530f8c60c1060f9f003e214cc341d35266philippe{
1817293d2530f8c60c1060f9f003e214cc341d35266philippe   if (VG_(clo_stats)
1827293d2530f8c60c1060f9f003e214cc341d35266philippe       && (VG_(clo_verbosity) > 2 || VG_(debugLog_getLevel) () >= 2)) {
1837293d2530f8c60c1060f9f003e214cc341d35266philippe      print_stats(ddpa);
1847293d2530f8c60c1060f9f003e214cc341d35266philippe   }
1857293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(HT_destruct) ( ddpa->ht_elements, htelem_dummyfree);
1867293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->ht_elements = NULL;
1877293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(deletePA) (ddpa->ht_node_pa);
1887293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->ht_node_pa = NULL;
1897293d2530f8c60c1060f9f003e214cc341d35266philippe}
1907293d2530f8c60c1060f9f003e214cc341d35266philippe
1917293d2530f8c60c1060f9f003e214cc341d35266philippevoid* VG_(allocEltDedupPA) (DedupPoolAlloc *ddpa, SizeT eltSzB, const void *elt)
1927293d2530f8c60c1060f9f003e214cc341d35266philippe{
1937293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_node ht_elt;
1947293d2530f8c60c1060f9f003e214cc341d35266philippe   void* elt_ins;
1957293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_node *ht_ins;
1967293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(ddpa);
1977293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert(ddpa->ht_elements);
1987293d2530f8c60c1060f9f003e214cc341d35266philippe   vg_assert (eltSzB <= ddpa->poolSzB);
1997293d2530f8c60c1060f9f003e214cc341d35266philippe
2007293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->nr_alloc_calls++;
2017293d2530f8c60c1060f9f003e214cc341d35266philippe
2027293d2530f8c60c1060f9f003e214cc341d35266philippe   // Currently using adler32 as hash function.
2037293d2530f8c60c1060f9f003e214cc341d35266philippe   // Many references tells adler32 is bad as a hash function.
2047293d2530f8c60c1060f9f003e214cc341d35266philippe   // And effectively, some tests on dwarf debug string shows
2057293d2530f8c60c1060f9f003e214cc341d35266philippe   // a lot of collisions (at least for short elements).
2067293d2530f8c60c1060f9f003e214cc341d35266philippe   // (A lot can be 10% of the elements colliding, even on
2077293d2530f8c60c1060f9f003e214cc341d35266philippe   // small nr of elements such as 10_000).
2087293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_elt.key = VG_(adler32) (0, NULL, 0);
2097293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_elt.key = VG_(adler32) (ht_elt.key, (UChar*)elt, eltSzB);
2107293d2530f8c60c1060f9f003e214cc341d35266philippe
2117293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_elt.eltSzB = eltSzB;
2127293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_elt.elt = (UChar*) elt;
2137293d2530f8c60c1060f9f003e214cc341d35266philippe
2147293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_ins = VG_(HT_gen_lookup) (ddpa->ht_elements, &ht_elt, cmp_pool_elt);
2157293d2530f8c60c1060f9f003e214cc341d35266philippe   if (ht_ins)
2167293d2530f8c60c1060f9f003e214cc341d35266philippe      return ht_ins->elt;
2177293d2530f8c60c1060f9f003e214cc341d35266philippe
2187293d2530f8c60c1060f9f003e214cc341d35266philippe   /* Not found -> we need to allocate a new element from the pool
2197293d2530f8c60c1060f9f003e214cc341d35266philippe      and insert it in the hash table of inserted elements. */
2207293d2530f8c60c1060f9f003e214cc341d35266philippe
2217293d2530f8c60c1060f9f003e214cc341d35266philippe   // Add a new pool if not enough space in the current pool
2227293d2530f8c60c1060f9f003e214cc341d35266philippe   if (UNLIKELY(ddpa->curpool_free + eltSzB - 1 > ddpa->curpool_limit)) {
2237293d2530f8c60c1060f9f003e214cc341d35266philippe      ddpa_add_new_pool(ddpa);
2247293d2530f8c60c1060f9f003e214cc341d35266philippe   }
2257293d2530f8c60c1060f9f003e214cc341d35266philippe
2267293d2530f8c60c1060f9f003e214cc341d35266philippe   elt_ins = ddpa->curpool_free;
2277293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(memcpy)(elt_ins, elt, eltSzB);
2287293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa->curpool_free = ddpa->curpool_free + eltSzB;
2297293d2530f8c60c1060f9f003e214cc341d35266philippe   ddpa_align_curpool_free (ddpa);
2307293d2530f8c60c1060f9f003e214cc341d35266philippe
2317293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_ins = VG_(allocEltPA) (ddpa->ht_node_pa);
2327293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_ins->key = ht_elt.key;
2337293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_ins->eltSzB = eltSzB;
2347293d2530f8c60c1060f9f003e214cc341d35266philippe   ht_ins->elt = elt_ins;
2357293d2530f8c60c1060f9f003e214cc341d35266philippe   VG_(HT_add_node)(ddpa->ht_elements, ht_ins);
2367293d2530f8c60c1060f9f003e214cc341d35266philippe   return elt_ins;
2377293d2530f8c60c1060f9f003e214cc341d35266philippe}
238