* src/lisp.h (DOHASH): Handle rehashing (bug#68690)
authorStefan Monnier <monnier@iro.umontreal.ca>
Wed, 24 Jan 2024 19:52:09 +0000 (14:52 -0500)
committerStefan Monnier <monnier@iro.umontreal.ca>
Wed, 24 Jan 2024 19:52:31 +0000 (14:52 -0500)
I gave too much credit to the comment, and didn't realize that macro
was used in places that didn't obey the comment.
This macro is getting pretty hideous!

src/lisp.h

index f822417ffb1c8158f0126c62a65f5d2a7fc58eb0..d07d9d14e2f6161d23c5830471035a6fda703b20 100644 (file)
@@ -2604,20 +2604,30 @@ hash_from_key (struct Lisp_Hash_Table *h, Lisp_Object key)
 }
 
 /* Iterate K and V as key and value of valid entries in hash table H.
-   The body may remove the current entry or alter its value slot, but not
-   mutate TABLE in any other way.  */
-#define DOHASH(h, k, v)                                                        \
-  for (Lisp_Object *dohash_##k##_##v##_kv = (h)->key_and_value,                \
-                   *dohash_##k##_##v##_end = dohash_##k##_##v##_kv     \
-                                             + 2 * HASH_TABLE_SIZE (h),        \
-                   k, v;                                               \
-       dohash_##k##_##v##_kv < dohash_##k##_##v##_end                  \
-       && (k = dohash_##k##_##v##_kv[0],                               \
-           v = dohash_##k##_##v##_kv[1], /*maybe unsed*/ (void)v,       \
-           true);                                                      \
-        dohash_##k##_##v##_kv += 2)                                    \
-    if (hash_unused_entry_key_p (k))                                   \
-      ;                                                                        \
+   The body may mutate the hash-table.  */
+#define DOHASH(h, k, v)                                                         \
+  for (Lisp_Object *dohash_##k##_##v##_base = (h)->key_and_value,       \
+                   *dohash_##k##_##v##_kv   = dohash_##k##_##v##_base,  \
+                   *dohash_##k##_##v##_end  = dohash_##k##_##v##_base   \
+                                              + 2 * HASH_TABLE_SIZE (h), \
+                   k, v;                                                \
+       dohash_##k##_##v##_kv < dohash_##k##_##v##_end                   \
+       && (dohash_##k##_##v##_base == (h)->key_and_value                 \
+           /* The `key_and_value` table has been reallocated!  */        \
+           || (dohash_##k##_##v##_kv                                     \
+                  = (dohash_##k##_##v##_kv - dohash_##k##_##v##_base)   \
+                    + (h)->key_and_value,                                \
+               dohash_##k##_##v##_base = (h)->key_and_value,             \
+               dohash_##k##_##v##_end  = dohash_##k##_##v##_base        \
+                                         + 2 * HASH_TABLE_SIZE (h),      \
+               /* Check again, in case the table has shrunk.  */         \
+               dohash_##k##_##v##_kv < dohash_##k##_##v##_end))          \
+       && (k = dohash_##k##_##v##_kv[0],                                 \
+           v = dohash_##k##_##v##_kv[1], /*maybe unused*/ (void)v,       \
+           true);                                                       \
+        dohash_##k##_##v##_kv += 2)                                     \
+    if (hash_unused_entry_key_p (k))                                    \
+      ;                                                                         \
     else