]> git.eshelyaron.com Git - emacs.git/commitdiff
* 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)
committerEshel Yaron <me@eshelyaron.com>
Thu, 25 Jan 2024 18:04:36 +0000 (19:04 +0100)
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!

(cherry picked from commit ad004f10f3668d464d32ed8da18639da9bcc01bb)

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