summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMattias EngdegÄrd <mattiase@acm.org>2024-01-19 15:17:52 +0100
committerMattias EngdegÄrd <mattiase@acm.org>2024-01-21 11:21:51 +0100
commitfec87a4b36a67688932e7bb7e1720bd2c4363a61 (patch)
tree8549ad5b17f75ba86a77e5fd8dea8a77bb3133af /src
parent0a07603ae8db41f69e83b1bfec6e28a92f737852 (diff)
downloademacs-fec87a4b36a67688932e7bb7e1720bd2c4363a61.tar.gz
emacs-fec87a4b36a67688932e7bb7e1720bd2c4363a61.tar.bz2
emacs-fec87a4b36a67688932e7bb7e1720bd2c4363a61.zip
Add C macro for hash table iteration
This removes some boilerplate code and further reduces dependencies on hash table implementation internals. * src/lisp.h (DOHASH): New. * src/comp.c (compile_function, Fcomp__compile_ctxt_to_file): * src/composite.c (composition_gstring_cache_clear_font): * src/emacs-module.c (module_global_reference_p): * src/fns.c (Fmaphash): * src/json.c (lisp_to_json_nonscalar_1): * src/minibuf.c (Ftest_completion): * src/print.c (print): Use it instead of a hand-written loop.
Diffstat (limited to 'src')
-rw-r--r--src/comp.c40
-rw-r--r--src/composite.c12
-rw-r--r--src/emacs-module.c9
-rw-r--r--src/fns.c9
-rw-r--r--src/json.c47
-rw-r--r--src/lisp.h8
-rw-r--r--src/minibuf.c4
-rw-r--r--src/print.c12
8 files changed, 59 insertions, 82 deletions
diff --git a/src/comp.c b/src/comp.c
index 3f9e738d9a7..25c4cb2f22c 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -4330,11 +4330,10 @@ compile_function (Lisp_Object func)
declare_block (Qentry);
Lisp_Object blocks = CALL1I (comp-func-blocks, func);
struct Lisp_Hash_Table *ht = XHASH_TABLE (blocks);
- for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (ht); i++)
+ DOHASH (ht, i)
{
Lisp_Object block_name = HASH_KEY (ht, i);
- if (!EQ (block_name, Qentry)
- && !hash_unused_entry_key_p (block_name))
+ if (!EQ (block_name, Qentry))
declare_block (block_name);
}
@@ -4344,24 +4343,21 @@ compile_function (Lisp_Object func)
gcc_jit_lvalue_as_rvalue (comp.func_relocs));
- for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (ht); i++)
+ DOHASH (ht, i)
{
Lisp_Object block_name = HASH_KEY (ht, i);
- if (!hash_unused_entry_key_p (block_name))
+ Lisp_Object block = HASH_VALUE (ht, i);
+ Lisp_Object insns = CALL1I (comp-block-insns, block);
+ if (NILP (block) || NILP (insns))
+ xsignal1 (Qnative_ice,
+ build_string ("basic block is missing or empty"));
+
+ comp.block = retrive_block (block_name);
+ while (CONSP (insns))
{
- Lisp_Object block = HASH_VALUE (ht, i);
- Lisp_Object insns = CALL1I (comp-block-insns, block);
- if (NILP (block) || NILP (insns))
- xsignal1 (Qnative_ice,
- build_string ("basic block is missing or empty"));
-
- comp.block = retrive_block (block_name);
- while (CONSP (insns))
- {
- Lisp_Object insn = XCAR (insns);
- emit_limple_insn (insn);
- insns = XCDR (insns);
- }
+ Lisp_Object insn = XCAR (insns);
+ emit_limple_insn (insn);
+ insns = XCDR (insns);
}
}
const char *err = gcc_jit_context_get_first_error (comp.ctxt);
@@ -4965,14 +4961,10 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file,
struct Lisp_Hash_Table *func_h =
XHASH_TABLE (CALL1I (comp-ctxt-funcs-h, Vcomp_ctxt));
- for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++)
- if (!hash_unused_entry_key_p (HASH_KEY (func_h, i)))
- declare_function (HASH_VALUE (func_h, i));
+ DOHASH (func_h, i) declare_function (HASH_VALUE (func_h, i));
/* Compile all functions. Can't be done before because the
relocation structs has to be already defined. */
- for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++)
- if (!hash_unused_entry_key_p (HASH_KEY (func_h, i)))
- compile_function (HASH_VALUE (func_h, i));
+ DOHASH (func_h, i) compile_function (HASH_VALUE (func_h, i));
/* Work around bug#46495 (GCC PR99126). */
#if defined (WIDE_EMACS_INT) \
diff --git a/src/composite.c b/src/composite.c
index 78c884dd72d..d9233fe0cc0 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -687,17 +687,13 @@ composition_gstring_cache_clear_font (Lisp_Object font_object)
{
struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
- for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
+ DOHASH (h, i)
{
Lisp_Object k = HASH_KEY (h, i);
+ Lisp_Object gstring = HASH_VALUE (h, i);
- if (!hash_unused_entry_key_p (k))
- {
- Lisp_Object gstring = HASH_VALUE (h, i);
-
- if (EQ (LGSTRING_FONT (gstring), font_object))
- hash_remove_from_table (h, k);
- }
+ if (EQ (LGSTRING_FONT (gstring), font_object))
+ hash_remove_from_table (h, k);
}
}
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 00ae33dfa2c..77dd2b9152c 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -410,12 +410,9 @@ module_global_reference_p (emacs_value v, ptrdiff_t *n)
struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
/* Note that we can't use `hash_lookup' because V might be a local
reference that's identical to some global reference. */
- for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
- {
- if (!hash_unused_entry_key_p (HASH_KEY (h, i))
- && &XMODULE_GLOBAL_REFERENCE (HASH_VALUE (h, i))->value == v)
- return true;
- }
+ DOHASH (h, i)
+ if (&XMODULE_GLOBAL_REFERENCE (HASH_VALUE (h, i))->value == v)
+ return true;
/* Only used for debugging, so we don't care about overflow, just
make sure the operation is defined. */
ckd_add (n, *n, h->count);
diff --git a/src/fns.c b/src/fns.c
index 15bbd270311..4531b237824 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -5655,14 +5655,7 @@ FUNCTION is called with two arguments, KEY and VALUE.
(Lisp_Object function, Lisp_Object table)
{
struct Lisp_Hash_Table *h = check_hash_table (table);
-
- for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
- {
- Lisp_Object k = HASH_KEY (h, i);
- if (!hash_unused_entry_key_p (k))
- call2 (function, k, HASH_VALUE (h, i));
- }
-
+ DOHASH (h, i) call2 (function, HASH_KEY (h, i), HASH_VALUE (h, i));
return Qnil;
}
diff --git a/src/json.c b/src/json.c
index 266905f1c34..5434780ba13 100644
--- a/src/json.c
+++ b/src/json.c
@@ -361,33 +361,30 @@ lisp_to_json_nonscalar_1 (Lisp_Object lisp,
json = json_check (json_object ());
count = SPECPDL_INDEX ();
record_unwind_protect_ptr (json_release_object, json);
- for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
+ DOHASH (h, i)
{
Lisp_Object key = HASH_KEY (h, i);
- if (!hash_unused_entry_key_p (key))
- {
- CHECK_STRING (key);
- Lisp_Object ekey = json_encode (key);
- /* We can't specify the length, so the string must be
- null-terminated. */
- check_string_without_embedded_nulls (ekey);
- const char *key_str = SSDATA (ekey);
- /* Reject duplicate keys. These are possible if the hash
- table test is not `equal'. */
- if (json_object_get (json, key_str) != NULL)
- wrong_type_argument (Qjson_value_p, lisp);
- int status
- = json_object_set_new (json, key_str,
- lisp_to_json (HASH_VALUE (h, i), conf));
- if (status == -1)
- {
- /* A failure can be caused either by an invalid key or
- by low memory. */
- json_check_utf8 (ekey);
- json_out_of_memory ();
- }
- }
- }
+ CHECK_STRING (key);
+ Lisp_Object ekey = json_encode (key);
+ /* We can't specify the length, so the string must be
+ null-terminated. */
+ check_string_without_embedded_nulls (ekey);
+ const char *key_str = SSDATA (ekey);
+ /* Reject duplicate keys. These are possible if the hash
+ table test is not `equal'. */
+ if (json_object_get (json, key_str) != NULL)
+ wrong_type_argument (Qjson_value_p, lisp);
+ int status
+ = json_object_set_new (json, key_str,
+ lisp_to_json (HASH_VALUE (h, i), conf));
+ if (status == -1)
+ {
+ /* A failure can be caused either by an invalid key or
+ by low memory. */
+ json_check_utf8 (ekey);
+ json_out_of_memory ();
+ }
+ }
}
else if (NILP (lisp))
return json_check (json_object ());
diff --git a/src/lisp.h b/src/lisp.h
index f0beafba42c..edea7cc23bb 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2579,6 +2579,14 @@ hash_from_key (struct Lisp_Hash_Table *h, Lisp_Object key)
return h->test->hashfn (key, h);
}
+/* Hash table iteration construct (roughly an inlined maphash):
+ Iterate IDXVAR as index over valid entries of TABLE.
+ The body may remove the current entry or alter its value slot, but not
+ mutate TABLE in any other way. */
+#define DOHASH(TABLE, IDXVAR) \
+ for (ptrdiff_t IDXVAR = 0; IDXVAR < (TABLE)->table_size; IDXVAR++) \
+ if (!hash_unused_entry_key_p (HASH_KEY (TABLE, IDXVAR)))
+
void hash_table_thaw (Lisp_Object hash_table);
/* Default size for hash tables if not specified. */
diff --git a/src/minibuf.c b/src/minibuf.c
index 8198dc0f360..857b62d94f0 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -2114,10 +2114,10 @@ the values STRING, PREDICATE and `lambda'. */)
goto found_matching_key;
}
else
- for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
+ DOHASH (h, j)
{
+ i = j;
tem = HASH_KEY (h, i);
- if (hash_unused_entry_key_p (tem)) continue;
Lisp_Object strkey = (SYMBOLP (tem) ? Fsymbol_name (tem) : tem);
if (!STRINGP (strkey)) continue;
if (BASE_EQ (Fcompare_strings (string, Qnil, Qnil,
diff --git a/src/print.c b/src/print.c
index 61999c096aa..c61fb3cd574 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1285,15 +1285,9 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
{ /* Remove unnecessary objects, which appear only once in OBJ;
that is, whose status is Qt. */
struct Lisp_Hash_Table *h = XHASH_TABLE (Vprint_number_table);
- ptrdiff_t i;
-
- for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
- {
- Lisp_Object key = HASH_KEY (h, i);
- if (!hash_unused_entry_key_p (key)
- && EQ (HASH_VALUE (h, i), Qt))
- Fremhash (key, Vprint_number_table);
- }
+ DOHASH (h, i)
+ if (EQ (HASH_VALUE (h, i), Qt))
+ Fremhash (HASH_KEY (h, i), Vprint_number_table);
}
}