Index: src/hash.c =================================================================== --- src/hash.c (revision 48465) +++ src/hash.c (working copy) @@ -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 @@ -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); - } + ); } /* Index: src/pmc/lexinfo.pmc =================================================================== --- src/pmc/lexinfo.pmc (revision 48465) +++ src/pmc/lexinfo.pmc (working copy) @@ -99,26 +99,12 @@ 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; + parrot_hash_iterate(hash, + PARROT_ASSERT(_bucket->key); + VTABLE_push_string(INTERP, result, (STRING *)_bucket->key); + ); - 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; - } - } - return result; } else Index: src/pmc/callcontext.pmc =================================================================== --- src/pmc/callcontext.pmc (revision 48465) +++ src/pmc/callcontext.pmc (working copy) @@ -378,17 +378,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); + ); } PARROT_CAN_RETURN_NULL @@ -402,19 +395,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; } @@ -604,17 +589,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); } @@ -642,17 +619,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); } Index: src/pmc/hashiterator.pmc =================================================================== --- src/pmc/hashiterator.pmc (revision 48465) +++ src/pmc/hashiterator.pmc (working copy) @@ -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(attrs->parrot_hash, attrs->bucket, attrs->pos) --attrs->elements; - return; } Index: src/packfile.c =================================================================== --- src/packfile.c (revision 48465) +++ src/packfile.c (working copy) @@ -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); } Index: include/parrot/hash.h =================================================================== --- include/parrot/hash.h (revision 48465) +++ include/parrot/hash.h (working copy) @@ -78,6 +78,33 @@ hash_hash_key_fn hash_val; }; +/* Utility macros - use them, do not reinvent the weel */ +#define parrot_hash_iterate(_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(_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 */