From 6ae1818de7ac98b7c1d8459adfcacb82d2ffa816 Mon Sep 17 00:00:00 2001 From: Luben Karavelov Date: Sat, 14 Aug 2010 20:12:46 +0300 Subject: [PATCH] Add hash iteration macros in hash.h and use them --- include/parrot/hash.h | 43 +++++++++++++++++ src/hash.c | 119 +++++++++++++-------------------------------- src/packfile.c | 22 ++------ src/pmc/callcontext.pmc | 59 +++++----------------- src/pmc/hashiterator.pmc | 17 +------ src/pmc/lexinfo.pmc | 22 ++------- 6 files changed, 103 insertions(+), 179 deletions(-) diff --git a/include/parrot/hash.h b/include/parrot/hash.h index 84e3c70..fe9bfba 100644 --- a/include/parrot/hash.h +++ b/include/parrot/hash.h @@ -78,6 +78,49 @@ struct _hash { 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) \ +{ \ + UINTVAL _found=0; \ + HashBucket *_bucket = (_hash)->buckets; \ + 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 */ diff --git a/src/hash.c b/src/hash.c index 7605693..968733b 100644 --- a/src/hash.c +++ b/src/hash.c @@ -512,22 +512,10 @@ static void 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 @@ static void 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 @@ static void 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 @@ hash_freeze(PARROT_INTERP, ARGIN(const Hash *hash), ARGMOD(PMC *info)) 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 @@ void 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 @@ parrot_hash_clone_prunable(PARROT_INTERP, ARGIN(const Hash *hash), 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_hash_clone_prunable(PARROT_INTERP, ARGIN(const Hash *hash), 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); - } + ); } /* diff --git a/src/packfile.c b/src/packfile.c index 7320776..672dbea 100644 --- a/src/packfile.c +++ b/src/packfile.c @@ -3471,22 +3471,12 @@ Parrot_destroy_constants(PARROT_INTERP) 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); } diff --git a/src/pmc/callcontext.pmc b/src/pmc/callcontext.pmc index a73503c..f2a5ac3 100644 --- a/src/pmc/callcontext.pmc +++ b/src/pmc/callcontext.pmc @@ -378,17 +378,10 @@ static void 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 @@ get_named_names(PARROT_INTERP, ARGIN(PMC *SELF)) /* 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 @@ stored.) 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 @@ stored.) } 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); } diff --git a/src/pmc/hashiterator.pmc b/src/pmc/hashiterator.pmc index 5e682c6..0207b77 100644 --- a/src/pmc/hashiterator.pmc +++ b/src/pmc/hashiterator.pmc @@ -78,24 +78,9 @@ static void 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; } diff --git a/src/pmc/lexinfo.pmc b/src/pmc/lexinfo.pmc index c029944..1caf6ec 100644 --- a/src/pmc/lexinfo.pmc +++ b/src/pmc/lexinfo.pmc @@ -99,25 +99,11 @@ C, which gets an array of the names of the symbols in this lexpad. 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; } -- 1.7.1