1
2/*--------------------------------------------------------------------*/
3/*--- An AVL tree based finite map for word keys and word values.  ---*/
4/*--- Inspired by Haskell's "FiniteMap" library.                   ---*/
5/*---                                                   m_wordfm.c ---*/
6/*--------------------------------------------------------------------*/
7
8/*
9   This file is part of Valgrind, a dynamic binary instrumentation
10   framework.
11
12   Copyright (C) 2007-2011 Julian Seward
13      jseward@acm.org
14
15   This code is based on previous work by Nicholas Nethercote
16   (coregrind/m_oset.c) which is
17
18   Copyright (C) 2005-2011 Nicholas Nethercote
19       njn@valgrind.org
20
21   which in turn was derived partially from:
22
23      AVL C library
24      Copyright (C) 2000,2002  Daniel Nagy
25
26      This program is free software; you can redistribute it and/or
27      modify it under the terms of the GNU General Public License as
28      published by the Free Software Foundation; either version 2 of
29      the License, or (at your option) any later version.
30      [...]
31
32      (taken from libavl-0.4/debian/copyright)
33
34   This program is free software; you can redistribute it and/or
35   modify it under the terms of the GNU General Public License as
36   published by the Free Software Foundation; either version 2 of the
37   License, or (at your option) any later version.
38
39   This program is distributed in the hope that it will be useful, but
40   WITHOUT ANY WARRANTY; without even the implied warranty of
41   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
42   General Public License for more details.
43
44   You should have received a copy of the GNU General Public License
45   along with this program; if not, write to the Free Software
46   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
47   02111-1307, USA.
48
49   The GNU General Public License is contained in the file COPYING.
50*/
51
52#include "pub_core_basics.h"
53#include "pub_core_libcassert.h"
54#include "pub_core_libcbase.h"
55#include "pub_core_wordfm.h"   /* self */
56
57
58//------------------------------------------------------------------//
59//---                           WordFM                           ---//
60//---                       Implementation                       ---//
61//------------------------------------------------------------------//
62
63/* One element of the AVL tree */
64typedef
65   struct _AvlNode {
66      UWord key;
67      UWord val;
68      struct _AvlNode* child[2]; /* [0] is left subtree, [1] is right */
69      Char balance; /* do not make this unsigned */
70   }
71   AvlNode;
72
73typedef
74   struct {
75      UWord w;
76      Bool b;
77   }
78   MaybeWord;
79
80#define WFM_STKMAX    32    // At most 2**32 entries can be iterated over
81
82struct _WordFM {
83   AvlNode* root;
84   void*    (*alloc_nofail)( HChar*, SizeT );
85   HChar*   cc;
86   void     (*dealloc)(void*);
87   Word     (*kCmp)(UWord,UWord);
88   AvlNode* nodeStack[WFM_STKMAX]; // Iterator node stack
89   Int      numStack[WFM_STKMAX];  // Iterator num stack
90   Int      stackTop;              // Iterator stack pointer, one past end
91};
92
93/* forward */
94static Bool avl_removeroot_wrk(AvlNode** t, Word(*kCmp)(UWord,UWord));
95
96/* Swing to the left.  Warning: no balance maintainance. */
97static void avl_swl ( AvlNode** root )
98{
99   AvlNode* a  = *root;
100   AvlNode* b  = a->child[1];
101   *root       = b;
102   a->child[1] = b->child[0];
103   b->child[0] = a;
104}
105
106/* Swing to the right.  Warning: no balance maintainance. */
107static void avl_swr ( AvlNode** root )
108{
109   AvlNode* a  = *root;
110   AvlNode* b  = a->child[0];
111   *root       = b;
112   a->child[0] = b->child[1];
113   b->child[1] = a;
114}
115
116/* Balance maintainance after especially nasty swings. */
117static void avl_nasty ( AvlNode* root )
118{
119   switch (root->balance) {
120      case -1:
121         root->child[0]->balance = 0;
122         root->child[1]->balance = 1;
123         break;
124      case 1:
125         root->child[0]->balance = -1;
126         root->child[1]->balance = 0;
127         break;
128      case 0:
129         root->child[0]->balance = 0;
130         root->child[1]->balance = 0;
131         break;
132      default:
133         tl_assert(0);
134   }
135   root->balance=0;
136}
137
138/* Find size of a non-NULL tree. */
139static UWord size_avl_nonNull ( AvlNode* nd )
140{
141   return 1 + (nd->child[0] ? size_avl_nonNull(nd->child[0]) : 0)
142            + (nd->child[1] ? size_avl_nonNull(nd->child[1]) : 0);
143}
144
145/* Unsignedly compare w1 and w2.  If w1 < w2, produce a negative
146   number; if w1 > w2 produce a positive number, and if w1 == w2
147   produce zero. */
148static inline Word cmp_unsigned_Words ( UWord w1, UWord w2 ) {
149   if (w1 < w2) return -1;
150   if (w1 > w2) return 1;
151   return 0;
152}
153
154/* Insert element a into the AVL tree t.  Returns True if the depth of
155   the tree has grown.  If element with that key is already present,
156   just copy a->val to existing node, first returning old ->val field
157   of existing node in *oldV, so that the caller can finalize it
158   however it wants.
159*/
160static
161Bool avl_insert_wrk ( AvlNode**         rootp,
162                      /*OUT*/MaybeWord* oldV,
163                      AvlNode*          a,
164                      Word              (*kCmp)(UWord,UWord) )
165{
166   Word cmpres;
167
168   /* initialize */
169   a->child[0] = 0;
170   a->child[1] = 0;
171   a->balance  = 0;
172   oldV->b     = False;
173
174   /* insert into an empty tree? */
175   if (!(*rootp)) {
176      (*rootp) = a;
177      return True;
178   }
179
180   cmpres = kCmp ? /*boxed*/   kCmp( (*rootp)->key, a->key )
181                 : /*unboxed*/ cmp_unsigned_Words( (UWord)(*rootp)->key,
182                                                   (UWord)a->key );
183
184   if (cmpres > 0) {
185      /* insert into the left subtree */
186      if ((*rootp)->child[0]) {
187         AvlNode* left_subtree = (*rootp)->child[0];
188         if (avl_insert_wrk(&left_subtree, oldV, a, kCmp)) {
189            switch ((*rootp)->balance--) {
190               case  1: return False;
191               case  0: return True;
192               case -1: break;
193               default: tl_assert(0);
194            }
195            if ((*rootp)->child[0]->balance < 0) {
196               avl_swr( rootp );
197               (*rootp)->balance = 0;
198               (*rootp)->child[1]->balance = 0;
199            } else {
200               avl_swl( &((*rootp)->child[0]) );
201               avl_swr( rootp );
202               avl_nasty( *rootp );
203            }
204         } else {
205            (*rootp)->child[0] = left_subtree;
206         }
207         return False;
208      } else {
209         (*rootp)->child[0] = a;
210         if ((*rootp)->balance--)
211            return False;
212         return True;
213      }
214      tl_assert(0);/*NOTREACHED*/
215   }
216   else
217   if (cmpres < 0) {
218      /* insert into the right subtree */
219      if ((*rootp)->child[1]) {
220         AvlNode* right_subtree = (*rootp)->child[1];
221         if (avl_insert_wrk(&right_subtree, oldV, a, kCmp)) {
222            switch((*rootp)->balance++){
223               case -1: return False;
224               case  0: return True;
225               case  1: break;
226               default: tl_assert(0);
227            }
228            if ((*rootp)->child[1]->balance > 0) {
229               avl_swl( rootp );
230               (*rootp)->balance = 0;
231               (*rootp)->child[0]->balance = 0;
232            } else {
233               avl_swr( &((*rootp)->child[1]) );
234               avl_swl( rootp );
235               avl_nasty( *rootp );
236            }
237         } else {
238            (*rootp)->child[1] = right_subtree;
239         }
240         return False;
241      } else {
242         (*rootp)->child[1] = a;
243         if ((*rootp)->balance++)
244            return False;
245         return True;
246      }
247      tl_assert(0);/*NOTREACHED*/
248   }
249   else {
250      /* cmpres == 0, a duplicate - replace the val, but don't
251         incorporate the node in the tree */
252      oldV->b = True;
253      oldV->w = (*rootp)->val;
254      (*rootp)->val = a->val;
255      return False;
256   }
257}
258
259/* Remove an element a from the AVL tree t.  a must be part of
260   the tree.  Returns True if the depth of the tree has shrunk.
261*/
262static
263Bool avl_remove_wrk ( AvlNode** rootp,
264                      AvlNode*  a,
265                      Word(*kCmp)(UWord,UWord) )
266{
267   Bool ch;
268   Word cmpres;
269   cmpres = kCmp ? /*boxed*/   kCmp( (*rootp)->key, a->key )
270                 : /*unboxed*/ cmp_unsigned_Words( (UWord)(*rootp)->key,
271                                                   (UWord)a->key );
272
273   if (cmpres > 0){
274      /* remove from the left subtree */
275      AvlNode* left_subtree = (*rootp)->child[0];
276      tl_assert(left_subtree);
277      ch = avl_remove_wrk(&left_subtree, a, kCmp);
278      (*rootp)->child[0]=left_subtree;
279      if (ch) {
280         switch ((*rootp)->balance++) {
281            case -1: return True;
282            case  0: return False;
283            case  1: break;
284            default: tl_assert(0);
285         }
286         switch ((*rootp)->child[1]->balance) {
287            case 0:
288               avl_swl( rootp );
289               (*rootp)->balance = -1;
290               (*rootp)->child[0]->balance = 1;
291               return False;
292            case 1:
293               avl_swl( rootp );
294               (*rootp)->balance = 0;
295               (*rootp)->child[0]->balance = 0;
296               return True;
297            case -1:
298               break;
299            default:
300               tl_assert(0);
301         }
302         avl_swr( &((*rootp)->child[1]) );
303         avl_swl( rootp );
304         avl_nasty( *rootp );
305         return True;
306      }
307   }
308   else
309   if (cmpres < 0) {
310      /* remove from the right subtree */
311      AvlNode* right_subtree = (*rootp)->child[1];
312      tl_assert(right_subtree);
313      ch = avl_remove_wrk(&right_subtree, a, kCmp);
314      (*rootp)->child[1] = right_subtree;
315      if (ch) {
316         switch ((*rootp)->balance--) {
317            case  1: return True;
318            case  0: return False;
319            case -1: break;
320            default: tl_assert(0);
321         }
322         switch ((*rootp)->child[0]->balance) {
323            case 0:
324               avl_swr( rootp );
325               (*rootp)->balance = 1;
326               (*rootp)->child[1]->balance = -1;
327               return False;
328            case -1:
329               avl_swr( rootp );
330               (*rootp)->balance = 0;
331               (*rootp)->child[1]->balance = 0;
332               return True;
333            case 1:
334               break;
335            default:
336               tl_assert(0);
337         }
338         avl_swl( &((*rootp)->child[0]) );
339         avl_swr( rootp );
340         avl_nasty( *rootp );
341         return True;
342      }
343   }
344   else {
345      tl_assert(cmpres == 0);
346      tl_assert((*rootp)==a);
347      return avl_removeroot_wrk(rootp, kCmp);
348   }
349   return 0;
350}
351
352/* Remove the root of the AVL tree *rootp.
353 * Warning: dumps core if *rootp is empty
354 */
355static
356Bool avl_removeroot_wrk ( AvlNode** rootp,
357                          Word(*kCmp)(UWord,UWord) )
358{
359   Bool     ch;
360   AvlNode* a;
361   if (!(*rootp)->child[0]) {
362      if (!(*rootp)->child[1]) {
363         (*rootp) = 0;
364         return True;
365      }
366      (*rootp) = (*rootp)->child[1];
367      return True;
368   }
369   if (!(*rootp)->child[1]) {
370      (*rootp) = (*rootp)->child[0];
371      return True;
372   }
373   if ((*rootp)->balance < 0) {
374      /* remove from the left subtree */
375      a = (*rootp)->child[0];
376      while (a->child[1]) a = a->child[1];
377   } else {
378      /* remove from the right subtree */
379      a = (*rootp)->child[1];
380      while (a->child[0]) a = a->child[0];
381   }
382   ch = avl_remove_wrk(rootp, a, kCmp);
383   a->child[0] = (*rootp)->child[0];
384   a->child[1] = (*rootp)->child[1];
385   a->balance  = (*rootp)->balance;
386   (*rootp)    = a;
387   if(a->balance == 0) return ch;
388   return False;
389}
390
391static
392AvlNode* avl_find_node ( AvlNode* t, Word k, Word(*kCmp)(UWord,UWord) )
393{
394   if (kCmp) {
395      /* Boxed comparisons */
396      Word cmpresS;
397      while (True) {
398         if (t == NULL) return NULL;
399         cmpresS = kCmp(t->key, k);
400         if (cmpresS > 0) t = t->child[0]; else
401         if (cmpresS < 0) t = t->child[1]; else
402         return t;
403      }
404   } else {
405      /* Unboxed comparisons */
406      Word  cmpresS; /* signed */
407      UWord cmpresU; /* unsigned */
408      while (True) {
409         if (t == NULL) return NULL; /* unlikely ==> predictable */
410         cmpresS = cmp_unsigned_Words( (UWord)t->key, (UWord)k );
411         if (cmpresS == 0) return t; /* unlikely ==> predictable */
412         cmpresU = (UWord)cmpresS;
413         cmpresU >>=/*unsigned*/ (8 * sizeof(cmpresU) - 1);
414         t = t->child[cmpresU];
415      }
416   }
417}
418
419static
420Bool avl_find_bounds ( AvlNode* t,
421                       /*OUT*/UWord* kMinP, /*OUT*/UWord* vMinP,
422                       /*OUT*/UWord* kMaxP, /*OUT*/UWord* vMaxP,
423                       UWord minKey, UWord minVal,
424                       UWord maxKey, UWord maxVal,
425                       UWord key,
426                       Word(*kCmp)(UWord,UWord) )
427{
428   UWord kLowerBound = minKey;
429   UWord vLowerBound = minVal;
430   UWord kUpperBound = maxKey;
431   UWord vUpperBound = maxVal;
432   while (t) {
433      Word cmpresS = kCmp ? kCmp(t->key, key)
434                          : cmp_unsigned_Words(t->key, key);
435      if (cmpresS < 0) {
436         kLowerBound = t->key;
437         vLowerBound = t->val;
438         t = t->child[1];
439         continue;
440      }
441      if (cmpresS > 0) {
442         kUpperBound = t->key;
443         vUpperBound = t->val;
444         t = t->child[0];
445         continue;
446      }
447      /* We should never get here.  If we do, it means the given key
448         is actually present in the tree, which means the original
449         call was invalid -- an error on the caller's part, and we
450         cannot give any meaningful values for the bounds.  (Well,
451         maybe we could, but we're not gonna.  Ner!) */
452      return False;
453   }
454   if (kMinP) *kMinP = kLowerBound;
455   if (vMinP) *vMinP = vLowerBound;
456   if (kMaxP) *kMaxP = kUpperBound;
457   if (vMaxP) *vMaxP = vUpperBound;
458   return True;
459}
460
461// Clear the iterator stack.
462static void stackClear(WordFM* fm)
463{
464   Int i;
465   tl_assert(fm);
466   for (i = 0; i < WFM_STKMAX; i++) {
467      fm->nodeStack[i] = NULL;
468      fm->numStack[i]  = 0;
469   }
470   fm->stackTop = 0;
471}
472
473// Push onto the iterator stack.
474static inline void stackPush(WordFM* fm, AvlNode* n, Int i)
475{
476   tl_assert(fm->stackTop < WFM_STKMAX);
477   tl_assert(1 <= i && i <= 3);
478   fm->nodeStack[fm->stackTop] = n;
479   fm-> numStack[fm->stackTop] = i;
480   fm->stackTop++;
481}
482
483// Pop from the iterator stack.
484static inline Bool stackPop(WordFM* fm, AvlNode** n, Int* i)
485{
486   tl_assert(fm->stackTop <= WFM_STKMAX);
487
488   if (fm->stackTop > 0) {
489      fm->stackTop--;
490      *n = fm->nodeStack[fm->stackTop];
491      *i = fm-> numStack[fm->stackTop];
492      tl_assert(1 <= *i && *i <= 3);
493      fm->nodeStack[fm->stackTop] = NULL;
494      fm-> numStack[fm->stackTop] = 0;
495      return True;
496   } else {
497      return False;
498   }
499}
500
501static
502AvlNode* avl_dopy ( AvlNode* nd,
503                    UWord(*dopyK)(UWord),
504                    UWord(*dopyV)(UWord),
505                    void*(alloc_nofail)(HChar*,SizeT),
506                    HChar* cc )
507{
508   AvlNode* nyu;
509   if (! nd)
510      return NULL;
511   nyu = alloc_nofail(cc, sizeof(AvlNode));
512   tl_assert(nyu);
513
514   nyu->child[0] = nd->child[0];
515   nyu->child[1] = nd->child[1];
516   nyu->balance = nd->balance;
517
518   /* Copy key */
519   if (dopyK) {
520      nyu->key = dopyK( nd->key );
521      if (nd->key != 0 && nyu->key == 0)
522         return NULL; /* oom in key dcopy */
523   } else {
524      /* copying assumedly unboxed keys */
525      nyu->key = nd->key;
526   }
527
528   /* Copy val */
529   if (dopyV) {
530      nyu->val = dopyV( nd->val );
531      if (nd->val != 0 && nyu->val == 0)
532         return NULL; /* oom in val dcopy */
533   } else {
534      /* copying assumedly unboxed vals */
535      nyu->val = nd->val;
536   }
537
538   /* Copy subtrees */
539   if (nyu->child[0]) {
540      nyu->child[0] = avl_dopy( nyu->child[0], dopyK, dopyV,
541                                alloc_nofail, cc );
542      if (! nyu->child[0])
543         return NULL;
544   }
545   if (nyu->child[1]) {
546      nyu->child[1] = avl_dopy( nyu->child[1], dopyK, dopyV,
547                                alloc_nofail, cc );
548      if (! nyu->child[1])
549         return NULL;
550   }
551
552   return nyu;
553}
554
555/* Initialise a WordFM. */
556static void initFM ( WordFM* fm,
557                     void*   (*alloc_nofail)( HChar*, SizeT ),
558                     HChar*  cc,
559                     void    (*dealloc)(void*),
560                     Word    (*kCmp)(UWord,UWord) )
561{
562   fm->root         = 0;
563   fm->kCmp         = kCmp;
564   fm->alloc_nofail = alloc_nofail;
565   fm->cc           = cc;
566   fm->dealloc      = dealloc;
567   fm->stackTop     = 0;
568}
569
570/* --- Public interface functions --- */
571
572/* Allocate and initialise a WordFM.  If kCmp is non-NULL, elements in
573   the set are ordered according to the ordering specified by kCmp,
574   which becomes obvious if you use VG_(initIterFM),
575   VG_(initIterAtFM), VG_(nextIterFM), VG_(doneIterFM) to iterate over
576   sections of the map, or the whole thing.  If kCmp is NULL then the
577   ordering used is unsigned word ordering (UWord) on the key
578   values. */
579WordFM* VG_(newFM) ( void* (*alloc_nofail)( HChar*, SizeT ),
580                     HChar* cc,
581                     void  (*dealloc)(void*),
582                     Word  (*kCmp)(UWord,UWord) )
583{
584   WordFM* fm = alloc_nofail(cc, sizeof(WordFM));
585   tl_assert(fm);
586   initFM(fm, alloc_nofail, cc, dealloc, kCmp);
587   return fm;
588}
589
590static void avl_free ( AvlNode* nd,
591                       void(*kFin)(UWord),
592                       void(*vFin)(UWord),
593                       void(*dealloc)(void*) )
594{
595   if (!nd)
596      return;
597   if (nd->child[0])
598      avl_free(nd->child[0], kFin, vFin, dealloc);
599   if (nd->child[1])
600      avl_free(nd->child[1], kFin, vFin, dealloc);
601   if (kFin)
602      kFin( nd->key );
603   if (vFin)
604      vFin( nd->val );
605   VG_(memset)(nd, 0, sizeof(AvlNode));
606   dealloc(nd);
607}
608
609/* Free up the FM.  If kFin is non-NULL, it is applied to keys
610   before the FM is deleted; ditto with vFin for vals. */
611void VG_(deleteFM) ( WordFM* fm, void(*kFin)(UWord), void(*vFin)(UWord) )
612{
613   void(*dealloc)(void*) = fm->dealloc;
614   avl_free( fm->root, kFin, vFin, dealloc );
615   VG_(memset)(fm, 0, sizeof(WordFM) );
616   dealloc(fm);
617}
618
619/* Add (k,v) to fm. */
620Bool VG_(addToFM) ( WordFM* fm, UWord k, UWord v )
621{
622   MaybeWord oldV;
623   AvlNode* node;
624   node = fm->alloc_nofail( fm->cc, sizeof(AvlNode) );
625   node->key = k;
626   node->val = v;
627   oldV.b = False;
628   oldV.w = 0;
629   avl_insert_wrk( &fm->root, &oldV, node, fm->kCmp );
630   //if (oldV.b && fm->vFin)
631   //   fm->vFin( oldV.w );
632   if (oldV.b)
633      fm->dealloc(node);
634   return oldV.b;
635}
636
637// Delete key from fm, returning associated key and val if found
638Bool VG_(delFromFM) ( WordFM* fm,
639                      /*OUT*/UWord* oldK, /*OUT*/UWord* oldV, UWord key )
640{
641   AvlNode* node = avl_find_node( fm->root, key, fm->kCmp );
642   if (node) {
643      avl_remove_wrk( &fm->root, node, fm->kCmp );
644      if (oldK)
645         *oldK = node->key;
646      if (oldV)
647         *oldV = node->val;
648      fm->dealloc(node);
649      return True;
650   } else {
651      return False;
652   }
653}
654
655// Look up in fm, assigning found key & val at spec'd addresses
656Bool VG_(lookupFM) ( WordFM* fm,
657                     /*OUT*/UWord* keyP, /*OUT*/UWord* valP, UWord key )
658{
659   AvlNode* node = avl_find_node( fm->root, key, fm->kCmp );
660   if (node) {
661      if (keyP)
662         *keyP = node->key;
663      if (valP)
664         *valP = node->val;
665      return True;
666   } else {
667      return False;
668   }
669}
670
671// See comment in pub_tool_wordfm.h for explanation
672Bool VG_(findBoundsFM)( WordFM* fm,
673                        /*OUT*/UWord* kMinP, /*OUT*/UWord* vMinP,
674                        /*OUT*/UWord* kMaxP, /*OUT*/UWord* vMaxP,
675                        UWord minKey, UWord minVal,
676                        UWord maxKey, UWord maxVal,
677                        UWord key )
678{
679   /* really we should assert that minKey <= key <= maxKey,
680      where <= is as defined by fm->kCmp. */
681   return avl_find_bounds( fm->root, kMinP, vMinP,
682                                     kMaxP, vMaxP,
683                                     minKey, minVal,
684                                     maxKey, maxVal,
685                                     key, fm->kCmp );
686}
687
688// See comment in pub_tool_wordfm.h for performance warning
689UWord VG_(sizeFM) ( WordFM* fm )
690{
691   // Hmm, this is a bad way to do this
692   return fm->root ? size_avl_nonNull( fm->root ) : 0;
693}
694
695// NB UNTESTED!  TEST BEFORE USE!
696//Bool VG_(isEmptyFM)( WordFM* fm )
697//{
698//   return fm->root ? False : True;
699//}
700
701// set up FM for iteration
702void VG_(initIterFM) ( WordFM* fm )
703{
704   tl_assert(fm);
705   stackClear(fm);
706   if (fm->root)
707      stackPush(fm, fm->root, 1);
708}
709
710// set up FM for iteration so that the first key subsequently produced
711// by VG_(nextIterFM) is the smallest key in the map >= start_at.
712// Naturally ">=" is defined by the comparison function supplied to
713// VG_(newFM), as documented above.
714void VG_(initIterAtFM) ( WordFM* fm, UWord start_at )
715{
716   Int     i;
717   AvlNode *n, *t;
718   Word    cmpresS; /* signed */
719   UWord   cmpresU; /* unsigned */
720
721   tl_assert(fm);
722   stackClear(fm);
723
724   if (!fm->root)
725      return;
726
727   n = NULL;
728   // We need to do regular search and fill in the stack.
729   t = fm->root;
730
731   while (True) {
732      if (t == NULL) return;
733
734      cmpresS
735         = fm->kCmp ? /*boxed*/   fm->kCmp( t->key, start_at )
736                    : /*unboxed*/ cmp_unsigned_Words( t->key, start_at );
737
738      if (cmpresS == 0) {
739         // We found the exact key -- we are done.
740         // The iteration should start with this node.
741         stackPush(fm, t, 2);
742         // The stack now looks like {2, 2, ... ,2, 2}
743         return;
744      }
745      cmpresU = (UWord)cmpresS;
746      cmpresU >>=/*unsigned*/ (8 * sizeof(cmpresU) - 1);
747      if (!cmpresU) {
748         // Push this node only if we go to the left child.
749         stackPush(fm, t, 2);
750      }
751      t = t->child[cmpresU];
752   }
753   if (stackPop(fm, &n, &i)) {
754      // If we've pushed something to stack and did not find the exact key,
755      // we must fix the top element of stack.
756      tl_assert(i == 2);
757      stackPush(fm, n, 3);
758      // the stack looks like {2, 2, ..., 2, 3}
759   }
760}
761
762// get next key/val pair.  Will tl_assert if fm has been modified
763// or looked up in since initIter{,At}FM was called.
764Bool VG_(nextIterFM) ( WordFM* fm, /*OUT*/UWord* pKey, /*OUT*/UWord* pVal )
765{
766   Int i = 0;
767   AvlNode* n = NULL;
768
769   tl_assert(fm);
770
771   // This in-order traversal requires each node to be pushed and popped
772   // three times.  These could be avoided by updating nodes in-situ on the
773   // top of the stack, but the push/pop cost is so small that it's worth
774   // keeping this loop in this simpler form.
775   while (stackPop(fm, &n, &i)) {
776      switch (i) {
777      case 1: case_1:
778         stackPush(fm, n, 2);
779         /* if (n->child[0])  stackPush(fm, n->child[0], 1); */
780         if (n->child[0]) { n = n->child[0]; goto case_1; }
781         break;
782      case 2:
783         stackPush(fm, n, 3);
784         if (pKey) *pKey = n->key;
785         if (pVal) *pVal = n->val;
786         return True;
787      case 3:
788         /* if (n->child[1]) stackPush(fm, n->child[1], 1); */
789         if (n->child[1]) { n = n->child[1]; goto case_1; }
790         break;
791      default:
792         tl_assert(0);
793      }
794   }
795
796   // Stack empty, iterator is exhausted, return NULL
797   return False;
798}
799
800// clear the I'm iterating flag
801void VG_(doneIterFM) ( WordFM* fm )
802{
803}
804
805WordFM* VG_(dopyFM) ( WordFM* fm, UWord(*dopyK)(UWord), UWord(*dopyV)(UWord) )
806{
807   WordFM* nyu;
808
809   /* can't clone the fm whilst iterating on it */
810   tl_assert(fm->stackTop == 0);
811
812   nyu = fm->alloc_nofail( fm->cc, sizeof(WordFM) );
813   tl_assert(nyu);
814
815   *nyu = *fm;
816
817   fm->stackTop = 0;
818   VG_(memset)(fm->nodeStack, 0, sizeof(fm->nodeStack));
819   VG_(memset)(fm->numStack, 0,  sizeof(fm->numStack));
820
821   if (nyu->root) {
822      nyu->root = avl_dopy( nyu->root, dopyK, dopyV,
823                            fm->alloc_nofail, fm->cc );
824      if (! nyu->root)
825         return NULL;
826   }
827
828   return nyu;
829}
830
831// admin: what's the 'common' allocation size (for tree nodes?)
832SizeT VG_(getNodeSizeFM)( void )
833{
834   return sizeof(AvlNode);
835}
836
837//------------------------------------------------------------------//
838//---                         end WordFM                         ---//
839//---                       Implementation                       ---//
840//------------------------------------------------------------------//
841
842//------------------------------------------------------------------//
843//---                WordBag (unboxed words only)                ---//
844//---                       Implementation                       ---//
845//------------------------------------------------------------------//
846
847/* A trivial container, to make it opaque. */
848struct _WordBag {
849   WordFM* fm;
850};
851
852WordBag* VG_(newBag) ( void* (*alloc_nofail)( HChar*, SizeT ),
853                       HChar* cc,
854                       void  (*dealloc)(void*) )
855{
856   WordBag* bag = alloc_nofail(cc, sizeof(WordBag));
857   bag->fm = VG_(newFM)( alloc_nofail, cc, dealloc, NULL );
858   return bag;
859}
860
861void VG_(deleteBag) ( WordBag* bag )
862{
863   void (*dealloc)(void*) = bag->fm->dealloc;
864   VG_(deleteFM)( bag->fm, NULL, NULL );
865   VG_(memset)(bag, 0, sizeof(WordBag));
866   dealloc(bag);
867}
868
869void VG_(addToBag)( WordBag* bag, UWord w )
870{
871   UWord key, count;
872   if (VG_(lookupFM)(bag->fm, &key, &count, w)) {
873      tl_assert(key == w);
874      tl_assert(count >= 1);
875      VG_(addToFM)(bag->fm, w, count+1);
876   } else {
877      VG_(addToFM)(bag->fm, w, 1);
878   }
879}
880
881UWord VG_(elemBag) ( WordBag* bag, UWord w )
882{
883   UWord key, count;
884   if (VG_(lookupFM)( bag->fm, &key, &count, w)) {
885      tl_assert(key == w);
886      tl_assert(count >= 1);
887      return count;
888   } else {
889      return 0;
890   }
891}
892
893UWord VG_(sizeUniqueBag) ( WordBag* bag )
894{
895   return VG_(sizeFM)( bag->fm );
896}
897
898static UWord sizeTotalBag_wrk ( AvlNode* nd )
899{
900   /* unchecked pre: nd is non-NULL */
901   UWord w = nd->val;
902   tl_assert(w >= 1);
903   if (nd->child[0])
904      w += sizeTotalBag_wrk(nd->child[0]);
905   if (nd->child[1])
906      w += sizeTotalBag_wrk(nd->child[1]);
907   return w;
908}
909UWord VG_(sizeTotalBag)( WordBag* bag )
910{
911   if (bag->fm->root)
912      return sizeTotalBag_wrk(bag->fm->root);
913   else
914      return 0;
915}
916
917Bool VG_(delFromBag)( WordBag* bag, UWord w )
918{
919   UWord key, count;
920   if (VG_(lookupFM)(bag->fm, &key, &count, w)) {
921      tl_assert(key == w);
922      tl_assert(count >= 1);
923      if (count > 1) {
924         VG_(addToFM)(bag->fm, w, count-1);
925      } else {
926         tl_assert(count == 1);
927         VG_(delFromFM)( bag->fm, NULL, NULL, w );
928      }
929      return True;
930   } else {
931      return False;
932   }
933}
934
935Bool VG_(isEmptyBag)( WordBag* bag )
936{
937   return VG_(sizeFM)(bag->fm) == 0;
938}
939
940Bool VG_(isSingletonTotalBag)( WordBag* bag )
941{
942   AvlNode* nd;
943   if (VG_(sizeFM)(bag->fm) != 1)
944      return False;
945   nd = bag->fm->root;
946   tl_assert(nd);
947   tl_assert(!nd->child[0]);
948   tl_assert(!nd->child[1]);
949   return nd->val == 1;
950}
951
952UWord VG_(anyElementOfBag)( WordBag* bag )
953{
954   /* Return an arbitrarily chosen element in the bag.  We might as
955      well return the one at the root of the underlying AVL tree. */
956   AvlNode* nd = bag->fm->root;
957   tl_assert(nd); /* if this fails, 'bag' is empty - caller is in error. */
958   tl_assert(nd->val >= 1);
959   return nd->key;
960}
961
962void VG_(initIterBag)( WordBag* bag )
963{
964   VG_(initIterFM)(bag->fm);
965}
966
967Bool VG_(nextIterBag)( WordBag* bag, /*OUT*/UWord* pVal, /*OUT*/UWord* pCount )
968{
969   return VG_(nextIterFM)( bag->fm, pVal, pCount );
970}
971
972void VG_(doneIterBag)( WordBag* bag )
973{
974   VG_(doneIterFM)( bag->fm );
975}
976
977//------------------------------------------------------------------//
978//---             end WordBag (unboxed words only)               ---//
979//---                       Implementation                       ---//
980//------------------------------------------------------------------//
981
982/*--------------------------------------------------------------------*/
983/*--- end                                               m_wordfm.c ---*/
984/*--------------------------------------------------------------------*/
985