diff options
author | Mattias EngdegÄrd <mattiase@acm.org> | 2024-01-25 18:56:03 +0100 |
---|---|---|
committer | Mattias EngdegÄrd <mattiase@acm.org> | 2024-01-27 12:37:53 +0100 |
commit | da726c6de201cdb9123bd99e22206dbed5fdc50f (patch) | |
tree | 7211aebebf8b41c6aa2206882ae2ed271eba479b /src/lisp.h | |
parent | 9b3f43fa08b2672a5ef33b872b2c6d1b0e881b88 (diff) | |
download | emacs-da726c6de201cdb9123bd99e22206dbed5fdc50f.tar.gz |
Add DOHASH_SAFE, make DOHASH faster (bug#68690)
Revert DOHASH to the fast (field-caching) implementation but with
an assertion to detect misuses. Add DOHASH_SAFE for use in
code that must tolerate arbitrary mutation of the table being
iterated through.
* src/lisp.h (DOHASH): Go back to fast design that only allows
restricted mutation, but with a checking assertion.
(DOHASH_SAFE): New macro that tolerates arbitrary mutation while being
much simpler (and acceptably fast).
* src/fns.c (Fmaphash):
* src/comp.c (compile_function, Fcomp__compile_ctxt_to_file):
Use DOHASH_SAFE.
Diffstat (limited to 'src/lisp.h')
-rw-r--r-- | src/lisp.h | 54 |
1 files changed, 30 insertions, 24 deletions
diff --git a/src/lisp.h b/src/lisp.h index d07d9d14e2f..c2dfd1afad5 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -2604,32 +2604,38 @@ 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 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)) \ - ; \ + 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), \ + *dohash_##k##_##v##_base = dohash_##k##_##v##_kv, \ + k, v; \ + 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); \ + eassert (dohash_##k##_##v##_base == (h)->key_and_value \ + && dohash_##k##_##v##_end \ + == dohash_##k##_##v##_base \ + + 2 * HASH_TABLE_SIZE (h)), \ + dohash_##k##_##v##_kv += 2) \ + if (hash_unused_entry_key_p (k)) \ + ; \ else +/* Iterate I as index of valid entries in hash table H. + Unlike DOHASH, this construct copes with arbitrary table mutations + in the body. The consequences of such mutations are limited to + whether and in what order entries are encountered by the loop + (which is usually bad enough), but not crashing or corrupting the + Lisp state. */ +#define DOHASH_SAFE(h, i) \ + for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); i++) \ + if (hash_unused_entry_key_p (HASH_KEY (h, i))) \ + ; \ + else void hash_table_thaw (Lisp_Object hash_table); |