[svn:parrot] r48569 - in trunk: include/parrot src src/pmc

chromatic at svn.parrot.org chromatic at svn.parrot.org
Thu Aug 19 16:06:21 UTC 2010


Author: chromatic
Date: Thu Aug 19 16:06:20 2010
New Revision: 48569
URL: https://trac.parrot.org/parrot/changeset/48569

Log:
[hash] Added hash iteration macros.

Patch courtesy Luben Karavelov, TT #1741.

Modified:
   trunk/include/parrot/hash.h
   trunk/src/hash.c
   trunk/src/packfile.c
   trunk/src/pmc/callcontext.pmc
   trunk/src/pmc/hashiterator.pmc
   trunk/src/pmc/lexinfo.pmc

Modified: trunk/include/parrot/hash.h
==============================================================================
--- trunk/include/parrot/hash.h	Thu Aug 19 06:49:05 2010	(r48568)
+++ trunk/include/parrot/hash.h	Thu Aug 19 16:06:20 2010	(r48569)
@@ -78,6 +78,49 @@
     hash_hash_key_fn hash_val;
 };
 
+/* Utility macros - use them, do not reinvent the weel */
+#define parrot_hash_iterate parrot_hash_iterate_linear
+
+#define parrot_hash_iterate_linear(_hash, _code)                            \
+{                                                                           \
+    HashBucket *_bucket = (_hash)->buckets;                                 \
+    UINTVAL     _found  = 0;                                                \
+    while (_found < _hash->entries){                                        \
+        if (_bucket->key){                                                  \
+            _code                                                           \
+            _found++;                                                       \
+        }                                                                   \
+       _bucket++;                                                           \
+    }                                                                       \
+}
+
+#define parrot_hash_iterate_indexed(_hash, _code)                           \
+{                                                                           \
+    INTVAL _loc;                                                            \
+    for (_loc = (_hash)->mask; _loc >= 0; --_loc) {                         \
+        HashBucket *_bucket = (_hash)->bucket_indices[_loc];                \
+        while (_bucket) {                                                   \
+            _code                                                           \
+            _bucket = _bucket->next;                                        \
+        }                                                                   \
+    }                                                                       \
+}
+
+
+#define parrot_hash_iterator_advance(_hash,_bucket,_loc)                    \
+{                                                                           \
+    /* Try to advance current bucket */                                     \
+    if ((_bucket))                                                          \
+        (_bucket) = (_bucket)->next;                                        \
+    while (!(_bucket)) {                                                    \
+        /* If there is no more buckets */                                   \
+        if ((_loc) == (INTVAL)(_hash)->mask+1)                              \
+            break;                                                          \
+        (_bucket) = (_hash)->bucket_indices[_loc++];                        \
+    }                                                                       \
+}
+
+
 typedef void (*value_free)(ARGFREE(void *));
 
 /* To avoid creating OrderedHashItem PMC we reuse FixedPMCArray PMC */

Modified: trunk/src/hash.c
==============================================================================
--- trunk/src/hash.c	Thu Aug 19 06:49:05 2010	(r48568)
+++ trunk/src/hash.c	Thu Aug 19 16:06:20 2010	(r48569)
@@ -512,22 +512,10 @@
 parrot_mark_hash_keys(PARROT_INTERP, ARGIN(Hash *hash))
 {
     ASSERT_ARGS(parrot_mark_hash_keys)
-    const UINTVAL entries = hash->entries;
-    UINTVAL found = 0;
-    UINTVAL i;
-
-    HashBucket *bucket = hash->buckets;
-
-    for (i= 0; i <= hash->mask; ++i, ++bucket) {
-        if (bucket->key){
-
-            PARROT_ASSERT(bucket->key);
-            Parrot_gc_mark_PObj_alive(interp, (PObj *)bucket->key);
-
-            if (++found >= entries)
-                break;
-        }
-    }
+    parrot_hash_iterate(hash,
+        PARROT_ASSERT(_bucket->key);
+        Parrot_gc_mark_PObj_alive(interp, (PObj *)_bucket->key);
+    );
 }
 
 
@@ -545,24 +533,13 @@
 parrot_mark_hash_values(PARROT_INTERP, ARGIN(Hash *hash))
 {
     ASSERT_ARGS(parrot_mark_hash_values)
-    const UINTVAL entries = hash->entries;
-    UINTVAL found = 0;
-    UINTVAL i;
-
-    HashBucket *bucket = hash->buckets;
-
-    for (i= 0; i <= hash->mask; ++i, ++bucket) {
-        if (bucket->key){
-
-            PARROT_ASSERT(bucket->value);
-            Parrot_gc_mark_PObj_alive(interp, (PObj *)bucket->value);
-
-            if (++found >= entries)
-                break;
-        }
-    }
+    parrot_hash_iterate(hash,
+        PARROT_ASSERT(_bucket->value);
+        Parrot_gc_mark_PObj_alive(interp, (PObj *)_bucket->value);
+    );
 }
 
+
 /*
 
 =item C<static void parrot_mark_hash_both(PARROT_INTERP, Hash *hash)>
@@ -577,24 +554,12 @@
 parrot_mark_hash_both(PARROT_INTERP, ARGIN(Hash *hash))
 {
     ASSERT_ARGS(parrot_mark_hash_both)
-    const UINTVAL entries = hash->entries;
-    UINTVAL found = 0;
-    UINTVAL i;
-
-    HashBucket *bucket = hash->buckets;
-
-    for (i= 0; i <= hash->mask; ++i, ++bucket) {
-        if (bucket->key){
-            PARROT_ASSERT(bucket->key);
-            Parrot_gc_mark_PObj_alive(interp, (PObj *)bucket->key);
-
-            PARROT_ASSERT(bucket->value);
-            Parrot_gc_mark_PObj_alive(interp, (PObj *)bucket->value);
-
-            if (++found >= entries)
-                break;
-        }
-    }
+    parrot_hash_iterate(hash,
+        PARROT_ASSERT(_bucket->key);
+        Parrot_gc_mark_PObj_alive(interp, (PObj *)_bucket->key);
+        PARROT_ASSERT(_bucket->value);
+        Parrot_gc_mark_PObj_alive(interp, (PObj *)_bucket->value);
+    );
 }
 
 /*
@@ -714,41 +679,38 @@
     const size_t           entries    = hash->entries;
     size_t                 i;
 
-    for (i = 0; i < entries; ++i) {
-        HashBucket * const b = hash->buckets + i;
-
+    parrot_hash_iterate(hash,
         switch (key_type) {
           case Hash_key_type_int:
-            VTABLE_push_integer(interp, info, (INTVAL)b->key);
+            VTABLE_push_integer(interp, info, (INTVAL)_bucket->key);
             break;
           case Hash_key_type_STRING:
-            VTABLE_push_string(interp, info, (STRING *)b->key);
+            VTABLE_push_string(interp, info, (STRING *)_bucket->key);
             break;
           case Hash_key_type_PMC:
-            VTABLE_push_pmc(interp, info, (PMC *)b->key);
+            VTABLE_push_pmc(interp, info, (PMC *)_bucket->key);
             break;
           default:
             Parrot_ex_throw_from_c_args(interp, NULL, 1,
                     "unimplemented key type");
             break;
         }
-
         switch (entry_type) {
           case enum_hash_int:
-            VTABLE_push_integer(interp, info, (INTVAL)b->value);
+            VTABLE_push_integer(interp, info, (INTVAL)_bucket->value);
             break;
           case enum_hash_string:
-            VTABLE_push_string(interp, info, (STRING *)b->value);
+            VTABLE_push_string(interp, info, (STRING *)_bucket->value);
             break;
           case enum_hash_pmc:
-            VTABLE_push_pmc(interp, info, (PMC *)b->value);
+            VTABLE_push_pmc(interp, info, (PMC *)_bucket->value);
             break;
           default:
             Parrot_ex_throw_from_c_args(interp, NULL, 1,
                     "unimplemented value type");
             break;
         }
-    }
+    );
 }
 
 
@@ -1121,17 +1083,10 @@
 parrot_chash_destroy(PARROT_INTERP, ARGMOD(Hash *hash))
 {
     ASSERT_ARGS(parrot_chash_destroy)
-    UINTVAL i;
-
-    for (i = 0; i <= hash->mask; ++i) {
-        HashBucket *bucket = hash->bucket_indices[i];
-        while (bucket) {
-            mem_gc_free(interp, bucket->key);
-            mem_gc_free(interp, bucket->value);
-            bucket = bucket->next;
-        }
-    }
-
+    parrot_hash_iterate(hash,
+        mem_gc_free(interp, _bucket->key);
+        mem_gc_free(interp, _bucket->value);
+    );
     parrot_hash_destroy(interp, hash);
 }
 
@@ -1472,33 +1427,30 @@
     ARGOUT(Hash *dest), int deep)
 {
     ASSERT_ARGS(parrot_hash_clone_prunable)
-    UINTVAL entries = hash->entries;
-    UINTVAL i;
 
-    for (i = 0; i < entries; ++i) {
+    parrot_hash_iterate(hash,
         void         *valtmp;
-        HashBucket   *b   = hash->buckets + i;
-        void * const  key = b->key;
+        void * const  key = _bucket->key;
 
         switch (hash->entry_type) {
           case enum_type_undef:
           case enum_type_ptr:
           case enum_type_INTVAL:
-            valtmp = (void *)b->value;
+            valtmp = (void *)_bucket->value;
             break;
 
           case enum_type_STRING:
-            valtmp = b->value;
+            valtmp = _bucket->value;
             break;
 
           case enum_type_PMC:
-            if (PMC_IS_NULL((PMC *)b->value))
+            if (PMC_IS_NULL((PMC *)_bucket->value))
                 valtmp = (void *)PMCNULL;
             else
                 if (deep)
-                    valtmp = (void *)VTABLE_clone(interp, (PMC*)b->value);
+                    valtmp = (void *)VTABLE_clone(interp, (PMC*)_bucket->value);
                 else
-                    valtmp = b->value;
+                    valtmp = _bucket->value;
             break;
 
           default:
@@ -1506,10 +1458,9 @@
             Parrot_ex_throw_from_c_args(interp, NULL, -1,
                     "hash corruption: type = %d\n", hash->entry_type);
         };
-
         if (key)
             parrot_hash_put(interp, dest, key, valtmp);
-    }
+    );
 }
 
 /*

Modified: trunk/src/packfile.c
==============================================================================
--- trunk/src/packfile.c	Thu Aug 19 06:49:05 2010	(r48568)
+++ trunk/src/packfile.c	Thu Aug 19 16:06:20 2010	(r48569)
@@ -3471,22 +3471,12 @@
     if (!hash)
         return;
 
-    for (i = 0; i <= hash->mask; ++i) {
-        HashBucket *bucket = hash->bucket_indices[i];
-
-        while (bucket) {
-            PackFile_ConstTable * const table      =
-                (PackFile_ConstTable *)bucket->key;
-            PackFile_Constant * const orig_consts = table->constants;
-            PackFile_Constant * const consts      =
-                (PackFile_Constant *) bucket->value;
-            INTVAL j;
-
-            mem_gc_free(interp, consts);
-            bucket = bucket->next;
-        }
-    }
-
+    parrot_hash_iterate(hash,
+        PackFile_ConstTable * const table     = (PackFile_ConstTable *)_bucket->key;
+        PackFile_Constant * const orig_consts = table->constants;
+        PackFile_Constant * const consts      = (PackFile_Constant *) _bucket->value;
+        mem_gc_free(interp, consts);
+    );
     parrot_hash_destroy(interp, hash);
 }
 

Modified: trunk/src/pmc/callcontext.pmc
==============================================================================
--- trunk/src/pmc/callcontext.pmc	Thu Aug 19 06:49:05 2010	(r48568)
+++ trunk/src/pmc/callcontext.pmc	Thu Aug 19 16:06:20 2010	(r48569)
@@ -468,17 +468,10 @@
 mark_hash(PARROT_INTERP, ARGIN(Hash *h))
 {
     ASSERT_ARGS(mark_hash)
-    INTVAL  i;
-
-    for (i = h->mask; i >= 0; --i) {
-        HashBucket *b = h->bucket_indices[i];
-
-        while (b) {
-            Parrot_gc_mark_STRING_alive(interp, (STRING *)b->key);
-            mark_cell(interp, (Pcc_cell *)b->value);
-            b = b->next;
-        }
-    }
+    parrot_hash_iterate(h,
+        Parrot_gc_mark_STRING_alive(interp, (STRING *)_bucket->key);
+        mark_cell(interp, (Pcc_cell *)_bucket->value);
+    );
 }
 
 /*
@@ -500,19 +493,11 @@
 
     /* yes, this *looks* risky, but it's a Parrot STRING hash internally */
     if (hash && hash->entries) {
-        UINTVAL i, j = 0;
+        UINTVAL j = 0;
         PMC *result = Parrot_pmc_new_init_int(interp, enum_class_FixedStringArray, hash->entries);
-
-        for (i = 0; i <= hash->mask; ++i) {
-            HashBucket *b = hash->bucket_indices[i];
-
-            while (b) {
-                VTABLE_set_string_keyed_int(interp, result,
-                    j++, (STRING *)b->key);
-                b = b->next;
-            }
-        }
-
+        parrot_hash_iterate(hash,
+            VTABLE_set_string_keyed_int(interp, result, j++, (STRING *)_bucket->key);
+        );
         return result;
     }
 
@@ -702,17 +687,9 @@
         GET_ATTR_hash(INTERP, SELF, hash);
 
         if (hash) {
-            UINTVAL i;
-
-            for (i = 0; i <= hash->mask; ++i) {
-                HashBucket *b = hash->bucket_indices[i];
-
-                while (b) {
-                    FREE_CELL(INTERP, (Pcc_cell *)b->value);
-                    b = b->next;
-                }
-            }
-
+            parrot_hash_iterate(hash,
+               FREE_CELL(INTERP, (Pcc_cell *)_bucket->value);
+            );
             parrot_hash_destroy(INTERP, hash);
             SET_ATTR_hash(INTERP, SELF, NULL);
         }
@@ -740,17 +717,9 @@
         }
 
         if (hash) {
-            UINTVAL i;
-
-            for (i = 0; i <= hash->mask; ++i) {
-                HashBucket *b = hash->bucket_indices[i];
-
-                while (b) {
-                    FREE_CELL(INTERP, (Pcc_cell *)b->value);
-                    b = b->next;
-                }
-            }
-
+            parrot_hash_iterate(hash,
+                FREE_CELL(INTERP, (Pcc_cell *)_bucket->value);
+            );
             parrot_hash_destroy(INTERP, hash);
         }
 

Modified: trunk/src/pmc/hashiterator.pmc
==============================================================================
--- trunk/src/pmc/hashiterator.pmc	Thu Aug 19 06:49:05 2010	(r48568)
+++ trunk/src/pmc/hashiterator.pmc	Thu Aug 19 16:06:20 2010	(r48569)
@@ -78,24 +78,9 @@
 advance_to_next(PARROT_INTERP, ARGMOD(PMC *self))
 {
     ASSERT_ARGS(advance_to_next)
-
     Parrot_HashIterator_attributes * const attrs  = PARROT_HASHITERATOR(self);
-    HashBucket                            *bucket = attrs->bucket;
-
-    /* Try to advance current bucket */
-    if (bucket)
-        bucket = bucket->next;
-
-    while (!bucket) {
-        /* If there is no more buckets */
-        if (attrs->pos == attrs->total_buckets)
-            break;
-
-        bucket = attrs->parrot_hash->bucket_indices[attrs->pos++];
-    }
-    attrs->bucket = bucket;
+    parrot_hash_iterator_advance(attrs->parrot_hash, attrs->bucket, attrs->pos);
     --attrs->elements;
-
     return;
 }
 

Modified: trunk/src/pmc/lexinfo.pmc
==============================================================================
--- trunk/src/pmc/lexinfo.pmc	Thu Aug 19 06:49:05 2010	(r48568)
+++ trunk/src/pmc/lexinfo.pmc	Thu Aug 19 16:06:20 2010	(r48569)
@@ -99,25 +99,11 @@
         if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "symbols"))) {
             PMC * const result    = Parrot_pmc_new(INTERP, enum_class_ResizableStringArray);
             const Hash *hash      = (Hash *)SELF.get_pointer();
-            const UINTVAL entries = hash->entries;
 
-            UINTVAL found   = 0;
-            INTVAL  i;
-
-            for (i = hash->mask; i >= 0; --i) {
-                HashBucket *bucket = hash->bucket_indices[i];
-                while (bucket) {
-                    if (++found > entries)
-                        Parrot_ex_throw_from_c_args(INTERP, NULL, 1,
-                            "Detected corruption at LexInfo hash %p entries %d",
-                            hash, (int)entries);
-
-                    PARROT_ASSERT(bucket->key);
-                    VTABLE_push_string(INTERP, result, (STRING *)bucket->key);
-
-                    bucket = bucket->next;
-                }
-            }
+            parrot_hash_iterate(hash,
+                PARROT_ASSERT(_bucket->key);
+                VTABLE_push_string(INTERP, result, (STRING *)_bucket->key);
+            );
 
             return result;
         }


More information about the parrot-commits mailing list