Author: sewardj Date: 2008-02-17 00:24:22 +0000 (Sun, 17 Feb 2008) New Revision: 7414
Log: * change the default ordering unboxed order from signed word (Word) to unsigned word (UWord) * change some size-of-the-OSet measures from Int to Word * add a method VG_(OSetGen_ResetIterAt) to start the iterator at a given point, analogous to hg_wordset.c:HG_(initIterAtFM) (Konstantin Serebryany) Modified: branches/DATASYMS/coregrind/m_oset.c branches/DATASYMS/include/pub_tool_oset.h Modified: branches/DATASYMS/coregrind/m_oset.c =================================================================== --- branches/DATASYMS/coregrind/m_oset.c 2008-02-16 02:37:03 UTC (rev 7413) +++ branches/DATASYMS/coregrind/m_oset.c 2008-02-17 00:24:22 UTC (rev 7414) @@ -113,7 +113,7 @@ OSetCmp_t cmp; // compare a key and an element, or NULL OSetAlloc_t alloc; // allocator OSetFree_t free; // deallocator - Int nElems; // number of elements in the tree + Word nElems; // number of elements in the tree AvlNode* root; // root node AvlNode* nodeStack[STACK_MAX]; // Iterator node stack @@ -175,8 +175,8 @@ // Compare the first word of each element. Inlining is *crucial*. static inline Word fast_cmp(void* k, AvlNode* n) { - Word w1 = *(Word*)k; - Word w2 = *(Word*)elem_of_node(n); + UWord w1 = *(UWord*)k; + UWord w2 = *(UWord*)elem_of_node(n); // In previous versions, we tried to do this faster by doing // "return w1 - w2". But it didn't work reliably, because the // complete result of subtracting two N-bit numbers is an N+1-bit @@ -189,7 +189,8 @@ } // Compare a key and an element. Inlining is *crucial*. -static inline Word slow_cmp(const AvlTree* t, const void* k, const AvlNode* n) +static +inline Word slow_cmp(const AvlTree* t, const void* k, const AvlNode* n) { return t->cmp(k, elem_of_node(n)); } @@ -314,7 +315,8 @@ void VG_(OSetGen_Destroy)(AvlTree* t) { AvlNode* n = NULL; - Int i = 0, sz = 0; + Int i = 0; + Word sz = 0; vg_assert(t); stackClear(t); @@ -460,8 +462,9 @@ vg_assert(t); - // Initialise. Even though OSetGen_AllocNode zeroes these fields, we should - // do it again in case a node is removed and then re-added to the tree. + // Initialise. Even though OSetGen_AllocNode zeroes these fields, + // we should do it again in case a node is removed and then + // re-added to the tree. n = node_of_elem(e); n->left = 0; n->right = 0; @@ -478,9 +481,9 @@ t->stackTop = 0; // So the iterator can't get out of sync } -void VG_(OSetWord_Insert)(AvlTree* t, Word val) +void VG_(OSetWord_Insert)(AvlTree* t, UWord val) { - Word* node = VG_(OSetGen_AllocNode)(t, sizeof(Word)); + Word* node = VG_(OSetGen_AllocNode)(t, sizeof(UWord)); *node = val; VG_(OSetGen_Insert)(t, node); } @@ -509,11 +512,11 @@ // elem_of_node because it saves about 10% on lookup time. This // shouldn't be very dangerous because each node will have been // checked on insertion. - Word w1 = *(Word*)k; - Word w2; + UWord w1 = *(UWord*)k; + UWord w2; while (True) { if (curr == NULL) return NULL; - w2 = *(Word*)elem_of_node_no_check(curr); + w2 = *(UWord*)elem_of_node_no_check(curr); if (w1 < w2) curr = curr->left; else if (w1 > w2) curr = curr->right; else return curr; @@ -551,7 +554,7 @@ return (NULL != VG_(OSetGen_Lookup)(t, k)); } -Bool VG_(OSetWord_Contains)(AvlTree* t, Word val) +Bool VG_(OSetWord_Contains)(AvlTree* t, UWord val) { return (NULL != VG_(OSetGen_Lookup)(t, &val)); } @@ -683,7 +686,8 @@ return False; } -// Remove and return the element matching the key 'k', or NULL if not present. +// Remove and return the element matching the key 'k', or NULL +// if not present. void* VG_(OSetGen_Remove)(AvlTree* t, void* k) { // Have to find the node first, then remove it. @@ -698,7 +702,7 @@ } } -Bool VG_(OSetWord_Remove)(AvlTree* t, Word val) +Bool VG_(OSetWord_Remove)(AvlTree* t, UWord val) { void* n = VG_(OSetGen_Remove)(t, &val); if (n) { @@ -760,9 +764,9 @@ return NULL; } -Bool VG_(OSetWord_Next)(AvlTree* t, Word* val) +Bool VG_(OSetWord_Next)(AvlTree* t, UWord* val) { - Word* n = VG_(OSetGen_Next)(t); + UWord* n = VG_(OSetGen_Next)(t); if (n) { *val = *n; return True; @@ -771,17 +775,81 @@ } } +// set up 'oset' for iteration so that the first key subsequently +// produced VG_(OSetGen_Next) is the smallest key in the map +// >= start_at. Naturally ">=" is defined by the comparison +// function supplied to VG_(OSetGen_Create). +void VG_(OSetGen_ResetIterAt)(AvlTree* oset, void* k) +{ + Int i; + AvlNode *n, *t; + Word cmpresS; /* signed */ + UWord cmpresU; /* unsigned */ + + tl_assert(oset); + stackClear(oset); + + if (!oset->root) + return; + + n = NULL; + // We need to do regular search and fill in the stack. + t = oset->root; + + while (True) { + if (t == NULL) return; + + if (oset->cmp) { + cmpresS = (Word)slow_cmp(oset, k, t); + } else { + /* this is believed to be correct, but really needs testing + before the assertion is removed. */ + vg_assert(0); + cmpresS = fast_cmp(k, t); + } + + /* Switch the sense of the comparison, since the comparison + order of args (k vs t) above is opposite to that of the + corresponding code in hg_wordfm.c. */ + if (cmpresS < 0) { cmpresS = 1; } + else if (cmpresS > 0) { cmpresS = -1; } + + if (cmpresS == 0) { + // We found the exact key -- we are done. + // The iteration should start with this node. + stackPush(oset, t, 2); + // The stack now looks like {2, 2, ... ,2, 2} + return; + } + cmpresU = (UWord)cmpresS; + cmpresU >>=/*unsigned*/ (8 * sizeof(cmpresU) - 1); + vg_assert(cmpresU == 0 || cmpresU == 1); + if (!cmpresU) { + // Push this node only if we go to the left child. + stackPush(oset, t, 2); + } + t = cmpresU==0 ? t->left : t->right; + } + if (stackPop(oset, &n, &i)) { + // If we've pushed something to stack and did not find the exact key, + // we must fix the top element of stack. + tl_assert(i == 2); + stackPush(oset, n, 3); + // the stack looks like {2, 2, ..., 2, 3} + } +} + /*--------------------------------------------------------------------*/ /*--- Miscellaneous operations ---*/ /*--------------------------------------------------------------------*/ -Int VG_(OSetGen_Size)(const AvlTree* t) +Word VG_(OSetGen_Size)(const AvlTree* t) { vg_assert(t); return t->nElems; } -Int VG_(OSetWord_Size)(AvlTree* t) +Word VG_(OSetWord_Size)(AvlTree* t) { return VG_(OSetGen_Size)(t); } Modified: branches/DATASYMS/include/pub_tool_oset.h =================================================================== --- branches/DATASYMS/include/pub_tool_oset.h 2008-02-16 02:37:03 UTC (rev 7413) +++ branches/DATASYMS/include/pub_tool_oset.h 2008-02-17 00:24:22 UTC (rev 7414) @@ -39,9 +39,9 @@ // It has two interfaces. // // - The "OSetWord_" interface provides an easier-to-use interface for the -// case where you just want to store Word-sized values. The user provides -// the allocation and deallocation functions, and possibly a comparison -// function. +// case where you just want to store UWord-sized values. The user +// provides the allocation and deallocation functions, and possibly a +// comparison function. // // - The "OSetGen_" interface provides a totally generic interface, which // allows any kind of structure to be put into the set. The user provides @@ -81,7 +81,7 @@ typedef void (*OSetFree_t) ( void* p ); /*--------------------------------------------------------------------*/ -/*--- Creating and destroying OSets (Word) ---*/ +/*--- Creating and destroying OSets (UWord) ---*/ /*--------------------------------------------------------------------*/ // * Create: allocates and initialises the OSet. Arguments: @@ -102,7 +102,7 @@ extern void VG_(OSetWord_Destroy) ( OSet* os ); /*--------------------------------------------------------------------*/ -/*--- Operations on OSets (Word) ---*/ +/*--- Operations on OSets (UWord) ---*/ /*--------------------------------------------------------------------*/ // In everything that follows, the parameter 'key' is always the *address* @@ -124,8 +124,8 @@ // // * Next: Copies the next value according to the OSet's iterator into &val, // advances the iterator by one, and returns True; the elements are -// visited in order. Or, returns False if the iterator has reached the -// set's end. +// visited in increasing order of unsigned words (UWord). Or, returns +// False if the iterator has reached the set's end. // // You can thus iterate in order through a set like this: // @@ -141,12 +141,12 @@ // they will return False if VG_(OSetWord_Next)() is called without an // intervening call to VG_(OSetWord_ResetIter)(). -extern Int VG_(OSetWord_Size) ( OSet* os ); -extern void VG_(OSetWord_Insert) ( OSet* os, Word val ); -extern Bool VG_(OSetWord_Contains) ( OSet* os, Word val ); -extern Bool VG_(OSetWord_Remove) ( OSet* os, Word val ); +extern Word VG_(OSetWord_Size) ( OSet* os ); +extern void VG_(OSetWord_Insert) ( OSet* os, UWord val ); +extern Bool VG_(OSetWord_Contains) ( OSet* os, UWord val ); +extern Bool VG_(OSetWord_Remove) ( OSet* os, UWord val ); extern void VG_(OSetWord_ResetIter) ( OSet* os ); -extern Bool VG_(OSetWord_Next) ( OSet* os, Word* val ); +extern Bool VG_(OSetWord_Next) ( OSet* os, /*OUT*/UWord* val ); /*--------------------------------------------------------------------*/ @@ -234,15 +234,22 @@ // they will return NULL if VG_(OSetGen_Next)() is called without an // intervening call to VG_(OSetGen_ResetIter)(). -extern Int VG_(OSetGen_Size) ( const OSet* os ); +extern Word VG_(OSetGen_Size) ( const OSet* os ); extern void VG_(OSetGen_Insert) ( OSet* os, void* elem ); extern Bool VG_(OSetGen_Contains) ( const OSet* os, const void* key ); extern void* VG_(OSetGen_Lookup) ( const OSet* os, const void* key ); -extern void* VG_(OSetGen_LookupWithCmp)( OSet* os, const void* key, OSetCmp_t cmp ); +extern void* VG_(OSetGen_LookupWithCmp)( OSet* os, + const void* key, OSetCmp_t cmp ); extern void* VG_(OSetGen_Remove) ( OSet* os, void* key ); extern void VG_(OSetGen_ResetIter) ( OSet* os ); extern void* VG_(OSetGen_Next) ( OSet* os ); +// set up 'oset' for iteration so that the first key subsequently +// produced VG_(OSetGen_Next) is the smallest key in the map +// >= start_at. Naturally ">=" is defined by the comparison +// function supplied to VG_(OSetGen_Create). +extern void VG_(OSetGen_ResetIterAt) ( OSet* oset, void* key ); + #endif // __PUB_TOOL_OSET_H /*--------------------------------------------------------------------*/ ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ Valgrind-developers mailing list Valgrind-developers@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/valgrind-developers