Author: leo
Date: Mon Jan  9 03:25:19 2006
New Revision: 11014

Modified:
   trunk/include/parrot/hash.h
   trunk/src/hash.c
Log:
Hash - reverse bucket fill order

* hash buckets are now used from lo to hi addresses
* reverse iteration and free_list fill order
* split the hash->bu union into bucket_store and bucket_index pointers


Modified: trunk/include/parrot/hash.h
==============================================================================
--- trunk/include/parrot/hash.h (original)
+++ trunk/include/parrot/hash.h Mon Jan  9 03:25:19 2006
@@ -55,10 +55,8 @@ typedef struct _hashbucket {
 } HashBucket;
 
 typedef struct _hash {
-    union {
-       HashBucket **bi;        /* list of Bucket pointers */
-       HashBucket *bs;         /* store of buckets */
-    } bu;
+    HashBucket *bs;             /* store of buckets */
+    HashBucket **bi;            /* list of Bucket pointers */
     HashBucket *free_list;      /* empty buckets */
     UINTVAL entries;            /* Number of values stored in hashtable */
     UINTVAL mask;               /* alloced - 1 */

Modified: trunk/src/hash.c
==============================================================================
--- trunk/src/hash.c    (original)
+++ trunk/src/hash.c    Mon Jan  9 03:25:19 2006
@@ -14,8 +14,7 @@ creation the types of key and value as w
 hashing functions can be set.
 
 This hash implementation uses just one piece of malloced memory. The
-C<< hash->bu >> union points into this regions. At positive indices are
-bucket pointers, at negative indices is the bucket store itself.
+C<< hash->bs >> bucket store points this regions. 
 
 This hash doesn't move during GC, therefore a lot of the old caveats
 don't apply.
@@ -200,7 +199,7 @@ mark_hash(Interp *interpreter, Hash *has
         return;
 
     for (i = 0; i <= hash->mask; i++) {
-        bucket = hash->bu.bi[i];
+        bucket = hash->bi[i];
         while (bucket) {
             if (++found > hash->entries)
                 internal_exception(1,
@@ -280,7 +279,7 @@ hash_freeze(Interp *interpreter, Hash *h
     HashBucket *b;
 
     for (i = 0; i <= hash->mask; i++) {
-        b = hash->bu.bi[i];
+        b = hash->bi[i];
         while (b) {
             switch (hash->key_type) {
                 case Hash_key_type_STRING:
@@ -377,13 +376,13 @@ expand_hash(Interp *interpreter, Hash *h
        e.g. 3 buckets, 4 pointers:
 
          +---+---+---+-+-+-+-+
-        | bs <--    | -> bi |
+        | --> bs    | -> bi |
          +---+---+---+-+-+-+-+
         ^           ^
-        | old_mem   | hash->bu
+        | old_mem   | hash->bi
     */
     old_nb = N_BUCKETS(old_size);
-    old_mem = hash->bu.bs - old_nb;
+    old_mem = hash->bs;
     /*
      * resize mem
      */
@@ -393,7 +392,7 @@ expand_hash(Interp *interpreter, Hash *h
         |  bs       | old_bi    |  new_bi       |
          +---+---+---+---+---+---+-+-+-+-+-+-+-+-+
         ^                       ^
-        | new_mem               | hash->bu
+        | new_mem               | hash->bi
     */
     bs = new_mem;
     old_bi = (HashBucket**) (bs + old_nb);
@@ -404,7 +403,8 @@ expand_hash(Interp *interpreter, Hash *h
     mem_sys_memmove(new_bi, old_bi, old_size * sizeof(HashBucket*));
 
     /* update hash data */
-    hash->bu.bi = new_bi;
+    hash->bi = new_bi;
+    hash->bs = bs;
     hash->mask = new_size - 1;
 
     /* clear freshly allocated bucket index */
@@ -442,12 +442,10 @@ expand_hash(Interp *interpreter, Hash *h
                next_p = &b->next;
        }
     }
-    /* add new buckets to free_list */
-    /* TODO reverse free_list filling so that we can use
-     *      buckets[i] directly in an OrderedHash, *if* nothing
-     *      was deleted
+    /* add new buckets to free_list in reverse order
+     * lowest bucket is top on free list and will be used first
      */
-    for (i = 0, b = (HashBucket*)old_bi; i < old_nb; ++i, ++b) {
+    for (i = 0, b = (HashBucket*)new_bi - 1; i < old_nb; ++i, --b) {
        b->next = hash->free_list;
        b->key = b->value = NULL;
        hash->free_list = b;
@@ -571,33 +569,29 @@ init_hash(Interp *interpreter, Hash *has
      * - use the bucket store and bi inside this structure
      * - when reallocate copy this part
      */
-    hash->bu.bs = mem_sys_allocate(HASH_ALLOC_SIZE(INITIAL_BUCKETS));
+    bp = mem_sys_allocate(HASH_ALLOC_SIZE(INITIAL_BUCKETS));
     hash->free_list = NULL;
-    /* TODO reverse free_list filling so that we can use
-     *      buckets[i] directly in an OrderedHash, *if* nothing
-     *      was deleted
+    /* fill free_list from hi addresses so that we can use
+     * buckets[i] directly in an OrderedHash, *if* nothing
+     * was deleted
      */
-    for (i = 0, bp = hash->bu.bs; i < N_BUCKETS(INITIAL_BUCKETS); ++i, ++bp) {
+    hash->bs = bp;
+    bp += N_BUCKETS(INITIAL_BUCKETS);
+    hash->bi = (HashBucket**) bp;
+    for (i = 0, --bp; i < N_BUCKETS(INITIAL_BUCKETS); ++i, --bp) {
        bp->next = hash->free_list;
        bp->key = bp->value = NULL;
        hash->free_list = bp;
     }
-    /* see the graphic in expand_hash */
-    hash->bu.bs = bp;
     for (i = 0; i < INITIAL_BUCKETS; ++i) {
-       hash->bu.bi[i] = NULL;
+       hash->bi[i] = NULL;
     }
 }
 
 void
 hash_destroy(Interp * interpreter, Hash *hash)
 {
-    UINTVAL nb;
-    void *mem;
-
-    nb = N_BUCKETS(hash->mask + 1);
-    mem = hash->bu.bs - nb;
-    mem_sys_free(mem);
+    mem_sys_free(hash->bs);
     mem_sys_free(hash);
 }
 
@@ -691,21 +685,23 @@ hash_get_idx(Interp *interpreter, Hash *
     BucketIndex bi = (BucketIndex)PMC_data(key);
     HashBucket *b;
     void *res;
+    INTVAL size;
 
     /* idx directly in the bucket store, which is at negative
      * address from the data pointer
      */
     /* locate initial */
+    size = (INTVAL)N_BUCKETS(hash->mask + 1);
     if (bi == INITBucketIndex) {
         i = 0;
         PMC_data(key) = NULL;
     }
-    else if (i >= (INTVAL)N_BUCKETS(hash->mask + 1)) {
+    else if (i >= size || i < 0) {
         PMC_int_val(key) = -1;
         return NULL;
     }
     res = NULL;
-    for (b = hash->bu.bs-i-1; i < (INTVAL)N_BUCKETS(hash->mask + 1); ++i, --b) 
{
+    for (b = hash->bs + i; i < size ; ++i, ++b) {
        /* XXX int keys may be zero - use different iterator
         */
        if (b->key) {
@@ -717,7 +713,7 @@ hash_get_idx(Interp *interpreter, Hash *
             }
         }
     }
-    if (i >= (INTVAL)N_BUCKETS(hash->mask + 1))
+    if (i >= size)
         i = -1;
     PMC_int_val(key) = i;
     return res;
@@ -738,7 +734,7 @@ HashBucket *
 hash_get_bucket(Interp *interpreter, Hash *hash, void *key)
 {
     UINTVAL hashval = (hash->hash_val)(interpreter, key, hash->seed);
-    HashBucket *bucket = hash->bu.bi[hashval & hash->mask];
+    HashBucket *bucket = hash->bi[hashval & hash->mask];
     while (bucket) {
        /* store hash_val or not */
         if ((hash->compare)(interpreter, key, bucket->key) == 0)
@@ -800,7 +796,7 @@ HashBucket*
 hash_put(Interp *interpreter, Hash *hash, void *key, void *value)
 {
     UINTVAL hashval = (hash->hash_val)(interpreter, key, hash->seed);
-    HashBucket *bucket = hash->bu.bi[hashval & hash->mask];
+    HashBucket *bucket = hash->bi[hashval & hash->mask];
     while (bucket) {
        /* store hash_val or not */
         if ((hash->compare)(interpreter, key, bucket->key) == 0)
@@ -829,8 +825,8 @@ hash_put(Interp *interpreter, Hash *hash
        hash->free_list = bucket->next;
         bucket->key = key;
         bucket->value = value;
-       bucket->next = hash->bu.bi[hashval & hash->mask];
-       hash->bu.bi[hashval & hash->mask] = bucket;
+       bucket->next = hash->bi[hashval & hash->mask];
+       hash->bi[hashval & hash->mask] = bucket;
     }
     return bucket;
 }
@@ -855,12 +851,12 @@ hash_delete(Interp *interpreter, Hash *h
 
     hashval = (hash->hash_val)(interpreter, key, hash->seed) & hash->mask;
 
-    for (bucket = hash->bu.bi[hashval]; bucket; bucket = bucket->next) {
+    for (bucket = hash->bi[hashval]; bucket; bucket = bucket->next) {
         if ((hash->compare)(interpreter, key, bucket->key) == 0) {
             if (prev)
                 prev->next = bucket->next;
             else {
-                hash->bu.bi[hashval] = bucket->next;
+                hash->bi[hashval] = bucket->next;
             }
             hash->entries--;
             bucket->next = hash->free_list;
@@ -892,7 +888,7 @@ hash_clone(Interp *interp, Hash *hash, H
     new_hash_x(interp, dest, hash->entry_type,
             hash->key_type, hash->compare, hash->hash_val);
     for (i = 0; i <= hash->mask; i++) {
-        b = hash->bu.bi[i];
+        b = hash->bi[i];
         while (b) {
             void *key = b->key;
             void *valtmp;

Reply via email to