Author: chromatic
Date: Fri Jul 18 14:25:41 2008
New Revision: 29597

Modified:
   trunk/src/hash.c

Log:
[src] Added three separate functions for hash marking, so that mark_hash() can
check whether to mark some combination of keys and values once, not for each
hash bucket.  An optimizing compiler should inline them, but they may need the
PARROT_INLINE hint.

Modified: trunk/src/hash.c
==============================================================================
--- trunk/src/hash.c    (original)
+++ trunk/src/hash.c    Fri Jul 18 14:25:41 2008
@@ -114,6 +114,15 @@
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
+static void
+parrot_mark_hash_keys(PARROT_INTERP, ARGIN(Hash *));
+
+static void
+parrot_mark_hash_values(PARROT_INTERP, ARGIN(Hash *));
+
+static void
+parrot_mark_hash_both(PARROT_INTERP, ARGIN(Hash *));
+
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will 
be lost. */
 /* HEADERIZER END: static */
 
@@ -338,10 +347,24 @@
     ||  hash->key_type == Hash_key_type_PMC)
         mark_key = 1;
 
-    if (!mark_key && !mark_value)
-        return;
+    if (mark_key) {
+        if (mark_value)
+            parrot_mark_hash_both(interp, hash);
+        else
+            parrot_mark_hash_keys(interp, hash);
+    }
+    else {
+        if (mark_value)
+            parrot_mark_hash_values(interp, hash);
+    }
+}
 
-    entries = hash->entries;
+static void
+parrot_mark_hash_keys(PARROT_INTERP, ARGIN(Hash *hash))
+{
+    UINTVAL entries = hash->entries;
+    UINTVAL found   = 0;
+    INTVAL  i;
 
     for (i = hash->mask; i >= 0; --i) {
         HashBucket *bucket = hash->bi[i];
@@ -352,15 +375,59 @@
                         "Detected hash corruption at hash %p entries %d",
                         hash, (int)entries);
 
-            if (mark_key) {
-                PARROT_ASSERT(bucket->key);
-                pobject_lives(interp, (PObj *)bucket->key);
-            }
+            PARROT_ASSERT(bucket->key);
+            pobject_lives(interp, (PObj *)bucket->key);
 
-            if (mark_value) {
-                PARROT_ASSERT(bucket->value);
-                pobject_lives(interp, (PObj *)bucket->value);
-            }
+            bucket = bucket->next;
+        }
+    }
+}
+
+static void
+parrot_mark_hash_values(PARROT_INTERP, ARGIN(Hash *hash))
+{
+    UINTVAL entries = hash->entries;
+    UINTVAL found   = 0;
+    INTVAL  i;
+
+    for (i = hash->mask; i >= 0; --i) {
+        HashBucket *bucket = hash->bi[i];
+
+        while (bucket) {
+            if (++found > entries)
+                real_exception(interp, NULL, 1,
+                        "Detected hash corruption at hash %p entries %d",
+                        hash, (int)entries);
+
+            PARROT_ASSERT(bucket->value);
+            pobject_lives(interp, (PObj *)bucket->value);
+
+            bucket = bucket->next;
+        }
+    }
+}
+
+static void
+parrot_mark_hash_both(PARROT_INTERP, ARGIN(Hash *hash))
+{
+    UINTVAL entries = hash->entries;
+    UINTVAL found   = 0;
+    INTVAL  i;
+
+    for (i = hash->mask; i >= 0; --i) {
+        HashBucket *bucket = hash->bi[i];
+
+        while (bucket) {
+            if (++found > entries)
+                real_exception(interp, NULL, 1,
+                        "Detected hash corruption at hash %p entries %d",
+                        hash, (int)entries);
+
+            PARROT_ASSERT(bucket->key);
+            pobject_lives(interp, (PObj *)bucket->key);
+
+            PARROT_ASSERT(bucket->value);
+            pobject_lives(interp, (PObj *)bucket->value);
 
             bucket = bucket->next;
         }

Reply via email to