[svn:parrot] r49089 - trunk/src

chromatic at svn.parrot.org chromatic at svn.parrot.org
Fri Sep 17 19:23:47 UTC 2010


Author: chromatic
Date: Fri Sep 17 19:23:46 2010
New Revision: 49089
URL: https://trac.parrot.org/parrot/changeset/49089

Log:
[Hash] Extracted two funcs from parrot_hash_put.

parrot_hash_get_bucket_string() is a type-safe way to find a bucket in a hash
given a STRING.

parrot_hash_store_value_in_bucket() is a reusable way to store a value in a
bucket after you've already fetched it.

Both of these functions are static.  If you ever use them outside of this file,
you will incur the wrath of premature optimization.

Modified:
   trunk/src/hash.c

Modified: trunk/src/hash.c
==============================================================================
--- trunk/src/hash.c	Fri Sep 17 17:51:12 2010	(r49088)
+++ trunk/src/hash.c	Fri Sep 17 19:23:46 2010	(r49089)
@@ -170,6 +170,26 @@
         __attribute__nonnull__(2)
         FUNC_MODIFIES(*s);
 
+PARROT_CAN_RETURN_NULL
+static HashBucket * parrot_hash_get_bucket_string(PARROT_INTERP,
+    ARGIN(Hash *hash),
+    ARGIN(STRING *s),
+    INTVAL hashval)
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
+
+static void parrot_hash_store_value_in_bucket(PARROT_INTERP,
+    ARGMOD(Hash *hash),
+    ARGMOD_NULLOK(HashBucket *bucket),
+    INTVAL hashval,
+    ARGIN_NULLOK(void *key),
+    ARGIN_NULLOK(void *value))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        FUNC_MODIFIES(*hash)
+        FUNC_MODIFIES(*bucket);
+
 static void parrot_mark_hash_both(PARROT_INTERP, ARGIN(Hash *hash))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
@@ -228,6 +248,14 @@
 #define ASSERT_ARGS_key_hash_STRING __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(s))
+#define ASSERT_ARGS_parrot_hash_get_bucket_string __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(hash) \
+    , PARROT_ASSERT_ARG(s))
+#define ASSERT_ARGS_parrot_hash_store_value_in_bucket \
+     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(hash))
 #define ASSERT_ARGS_parrot_mark_hash_both __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(hash))
@@ -1458,6 +1486,93 @@
 
 /*
 
+=item C<static HashBucket * parrot_hash_get_bucket_string(PARROT_INTERP, Hash
+*hash, STRING *s, INTVAL hashval)>
+
+Given a hash, a STRING key, and the hashval of the key, returns the appropriate
+bucket of the hash for the key.  This assumes buckets are already available, so
+ensure the hash has storage before calling this function.
+
+=cut
+
+*/
+
+PARROT_CAN_RETURN_NULL
+static HashBucket *
+parrot_hash_get_bucket_string(PARROT_INTERP, ARGIN(Hash *hash),
+        ARGIN(STRING *s), INTVAL hashval)
+{
+    ASSERT_ARGS(parrot_hash_get_bucket_string)
+    HashBucket *bucket = hash->index[hashval & hash->mask];
+
+    while (bucket) {
+        const STRING *s2 = (const STRING *)bucket->key;
+        if (s == s2)
+            break;
+
+        /* manually inline part of string_equal  */
+        if (hashval == s2->hashval) {
+            if (s->encoding == s2->encoding) {
+                if ((STRING_byte_length(s) == STRING_byte_length(s2))
+                && (memcmp(s->strstart, s2->strstart, STRING_byte_length(s)) == 0))
+                    break;
+            } else if (Parrot_str_equal(interp, s, s2))
+                    break;
+        }
+        bucket = bucket->next;
+    }
+
+    return bucket;
+}
+
+
+/*
+
+=item C<static void parrot_hash_store_value_in_bucket(PARROT_INTERP, Hash *hash,
+HashBucket *bucket, INTVAL hashval, void *key, void *value)>
+
+Given a hash, a bucket, the hashval of the key, the key, and its value, stores
+the value in the bucket.  The bucket can be NULL, in which case this function
+will allocate more storage as appropriate.
+
+Note that C<key> is B<not> copied.
+
+=cut
+
+*/
+
+static void
+parrot_hash_store_value_in_bucket(PARROT_INTERP, ARGMOD(Hash *hash),
+    ARGMOD_NULLOK(HashBucket *bucket), INTVAL hashval,
+    ARGIN_NULLOK(void *key), ARGIN_NULLOK(void *value))
+{
+    ASSERT_ARGS(parrot_hash_store_value_in_bucket)
+
+    /* If we have a bucket already, put the value in it. Otherwise, we need
+       to get a new bucket */
+    if (bucket)
+        bucket->value = value;
+    else {
+        /* Get a new bucket off the free list. If the free list is empty, we
+           expand the hash so we get more items on the free list */
+        if (!hash->free_list)
+            expand_hash(interp, hash);
+
+        bucket = hash->free_list;
+
+        /* Add the value to the new bucket, increasing the count of elements */
+        ++hash->entries;
+        hash->free_list                   = bucket->next;
+        bucket->key                       = key;
+        bucket->value                     = value;
+        bucket->next                      = hash->index[hashval & hash->mask];
+        hash->index[hashval & hash->mask] = bucket;
+    }
+}
+
+
+/*
+
 =item C<HashBucket* parrot_hash_put(PARROT_INTERP, Hash *hash, void *key, void
 *value)>
 
@@ -1484,25 +1599,9 @@
     }
     else {
         if (hash->key_type == Hash_key_type_STRING) {
-            const STRING * const s = (STRING *)key;
-            hashval                = key_hash_STRING(interp, (STRING *)key, hash->seed);
-            bucket                 = hash->index[hashval & hash->mask];
-
-            while (bucket) {
-                const STRING *s2 = (const STRING *)bucket->key;
-                if (s == s2)
-                    break;
-                /* manually inline part of string_equal  */
-                if (hashval == s2->hashval) {
-                    if (s->encoding == s2->encoding) {
-                        if ((STRING_byte_length(s) == STRING_byte_length(s2))
-                        && (memcmp(s->strstart, s2->strstart, STRING_byte_length(s)) == 0))
-                            break;
-                    } else if (Parrot_str_equal(interp, s, s2))
-                            break;
-                }
-                bucket = bucket->next;
-            }
+            STRING *s = (STRING *)key;
+            hashval = key_hash_STRING(interp, s, hash->seed);
+            bucket  = parrot_hash_get_bucket_string(interp, hash, s, hashval);
         }
         else {
             hashval = key_hash(interp, hash, key);
@@ -1516,26 +1615,8 @@
         }
     }
 
-    /* If we have a bucket already, put the value in it. Otherwise, we need
-       to get a new bucket */
-    if (bucket)
-        bucket->value = value;
-    else {
-        /* Get a new bucket off the free list. If the free list is empty, we
-           expand the hash so we get more items on the free list */
-        if (!hash->free_list)
-            expand_hash(interp, hash);
-
-        bucket = hash->free_list;
-
-        /* Add the value to the new bucket, increasing the count of elements */
-        ++hash->entries;
-        hash->free_list                   = bucket->next;
-        bucket->key                       = key;
-        bucket->value                     = value;
-        bucket->next                      = hash->index[hashval & hash->mask];
-        hash->index[hashval & hash->mask] = bucket;
-    }
+    parrot_hash_store_value_in_bucket(interp, hash, bucket, hashval,
+        key, value);
 
     return bucket;
 }


More information about the parrot-commits mailing list