diff options
| author | Mattias EngdegÄrd | 2024-01-19 15:17:52 +0100 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2024-01-21 11:21:51 +0100 |
| commit | fec87a4b36a67688932e7bb7e1720bd2c4363a61 (patch) | |
| tree | 8549ad5b17f75ba86a77e5fd8dea8a77bb3133af /src | |
| parent | 0a07603ae8db41f69e83b1bfec6e28a92f737852 (diff) | |
| download | emacs-fec87a4b36a67688932e7bb7e1720bd2c4363a61.tar.gz 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.c | 40 | ||||
| -rw-r--r-- | src/composite.c | 12 | ||||
| -rw-r--r-- | src/emacs-module.c | 9 | ||||
| -rw-r--r-- | src/fns.c | 9 | ||||
| -rw-r--r-- | src/json.c | 47 | ||||
| -rw-r--r-- | src/lisp.h | 8 | ||||
| -rw-r--r-- | src/minibuf.c | 4 | ||||
| -rw-r--r-- | src/print.c | 12 |
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) | |||
| 4330 | declare_block (Qentry); | 4330 | declare_block (Qentry); |
| 4331 | Lisp_Object blocks = CALL1I (comp-func-blocks, func); | 4331 | Lisp_Object blocks = CALL1I (comp-func-blocks, func); |
| 4332 | struct Lisp_Hash_Table *ht = XHASH_TABLE (blocks); | 4332 | struct Lisp_Hash_Table *ht = XHASH_TABLE (blocks); |
| 4333 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (ht); i++) | 4333 | DOHASH (ht, i) |
| 4334 | { | 4334 | { |
| 4335 | Lisp_Object block_name = HASH_KEY (ht, i); | 4335 | Lisp_Object block_name = HASH_KEY (ht, i); |
| 4336 | if (!EQ (block_name, Qentry) | 4336 | if (!EQ (block_name, Qentry)) |
| 4337 | && !hash_unused_entry_key_p (block_name)) | ||
| 4338 | declare_block (block_name); | 4337 | declare_block (block_name); |
| 4339 | } | 4338 | } |
| 4340 | 4339 | ||
| @@ -4344,24 +4343,21 @@ compile_function (Lisp_Object func) | |||
| 4344 | gcc_jit_lvalue_as_rvalue (comp.func_relocs)); | 4343 | gcc_jit_lvalue_as_rvalue (comp.func_relocs)); |
| 4345 | 4344 | ||
| 4346 | 4345 | ||
| 4347 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (ht); i++) | 4346 | DOHASH (ht, i) |
| 4348 | { | 4347 | { |
| 4349 | Lisp_Object block_name = HASH_KEY (ht, i); | 4348 | Lisp_Object block_name = HASH_KEY (ht, i); |
| 4350 | if (!hash_unused_entry_key_p (block_name)) | 4349 | Lisp_Object block = HASH_VALUE (ht, i); |
| 4350 | Lisp_Object insns = CALL1I (comp-block-insns, block); | ||
| 4351 | if (NILP (block) || NILP (insns)) | ||
| 4352 | xsignal1 (Qnative_ice, | ||
| 4353 | build_string ("basic block is missing or empty")); | ||
| 4354 | |||
| 4355 | comp.block = retrive_block (block_name); | ||
| 4356 | while (CONSP (insns)) | ||
| 4351 | { | 4357 | { |
| 4352 | Lisp_Object block = HASH_VALUE (ht, i); | 4358 | Lisp_Object insn = XCAR (insns); |
| 4353 | Lisp_Object insns = CALL1I (comp-block-insns, block); | 4359 | emit_limple_insn (insn); |
| 4354 | if (NILP (block) || NILP (insns)) | 4360 | insns = XCDR (insns); |
| 4355 | xsignal1 (Qnative_ice, | ||
| 4356 | build_string ("basic block is missing or empty")); | ||
| 4357 | |||
| 4358 | comp.block = retrive_block (block_name); | ||
| 4359 | while (CONSP (insns)) | ||
| 4360 | { | ||
| 4361 | Lisp_Object insn = XCAR (insns); | ||
| 4362 | emit_limple_insn (insn); | ||
| 4363 | insns = XCDR (insns); | ||
| 4364 | } | ||
| 4365 | } | 4361 | } |
| 4366 | } | 4362 | } |
| 4367 | const char *err = gcc_jit_context_get_first_error (comp.ctxt); | 4363 | 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, | |||
| 4965 | 4961 | ||
| 4966 | struct Lisp_Hash_Table *func_h = | 4962 | struct Lisp_Hash_Table *func_h = |
| 4967 | XHASH_TABLE (CALL1I (comp-ctxt-funcs-h, Vcomp_ctxt)); | 4963 | XHASH_TABLE (CALL1I (comp-ctxt-funcs-h, Vcomp_ctxt)); |
| 4968 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++) | 4964 | DOHASH (func_h, i) declare_function (HASH_VALUE (func_h, i)); |
| 4969 | if (!hash_unused_entry_key_p (HASH_KEY (func_h, i))) | ||
| 4970 | declare_function (HASH_VALUE (func_h, i)); | ||
| 4971 | /* Compile all functions. Can't be done before because the | 4965 | /* Compile all functions. Can't be done before because the |
| 4972 | relocation structs has to be already defined. */ | 4966 | relocation structs has to be already defined. */ |
| 4973 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++) | 4967 | DOHASH (func_h, i) compile_function (HASH_VALUE (func_h, i)); |
| 4974 | if (!hash_unused_entry_key_p (HASH_KEY (func_h, i))) | ||
| 4975 | compile_function (HASH_VALUE (func_h, i)); | ||
| 4976 | 4968 | ||
| 4977 | /* Work around bug#46495 (GCC PR99126). */ | 4969 | /* Work around bug#46495 (GCC PR99126). */ |
| 4978 | #if defined (WIDE_EMACS_INT) \ | 4970 | #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) | |||
| 687 | { | 687 | { |
| 688 | struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); | 688 | struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); |
| 689 | 689 | ||
| 690 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) | 690 | DOHASH (h, i) |
| 691 | { | 691 | { |
| 692 | Lisp_Object k = HASH_KEY (h, i); | 692 | Lisp_Object k = HASH_KEY (h, i); |
| 693 | Lisp_Object gstring = HASH_VALUE (h, i); | ||
| 693 | 694 | ||
| 694 | if (!hash_unused_entry_key_p (k)) | 695 | if (EQ (LGSTRING_FONT (gstring), font_object)) |
| 695 | { | 696 | hash_remove_from_table (h, k); |
| 696 | Lisp_Object gstring = HASH_VALUE (h, i); | ||
| 697 | |||
| 698 | if (EQ (LGSTRING_FONT (gstring), font_object)) | ||
| 699 | hash_remove_from_table (h, k); | ||
| 700 | } | ||
| 701 | } | 697 | } |
| 702 | } | 698 | } |
| 703 | 699 | ||
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) | |||
| 410 | struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash); | 410 | struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash); |
| 411 | /* Note that we can't use `hash_lookup' because V might be a local | 411 | /* Note that we can't use `hash_lookup' because V might be a local |
| 412 | reference that's identical to some global reference. */ | 412 | reference that's identical to some global reference. */ |
| 413 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) | 413 | DOHASH (h, i) |
| 414 | { | 414 | if (&XMODULE_GLOBAL_REFERENCE (HASH_VALUE (h, i))->value == v) |
| 415 | if (!hash_unused_entry_key_p (HASH_KEY (h, i)) | 415 | return true; |
| 416 | && &XMODULE_GLOBAL_REFERENCE (HASH_VALUE (h, i))->value == v) | ||
| 417 | return true; | ||
| 418 | } | ||
| 419 | /* Only used for debugging, so we don't care about overflow, just | 416 | /* Only used for debugging, so we don't care about overflow, just |
| 420 | make sure the operation is defined. */ | 417 | make sure the operation is defined. */ |
| 421 | ckd_add (n, *n, h->count); | 418 | ckd_add (n, *n, h->count); |
| @@ -5655,14 +5655,7 @@ FUNCTION is called with two arguments, KEY and VALUE. | |||
| 5655 | (Lisp_Object function, Lisp_Object table) | 5655 | (Lisp_Object function, Lisp_Object table) |
| 5656 | { | 5656 | { |
| 5657 | struct Lisp_Hash_Table *h = check_hash_table (table); | 5657 | struct Lisp_Hash_Table *h = check_hash_table (table); |
| 5658 | 5658 | DOHASH (h, i) call2 (function, HASH_KEY (h, i), HASH_VALUE (h, i)); | |
| 5659 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) | ||
| 5660 | { | ||
| 5661 | Lisp_Object k = HASH_KEY (h, i); | ||
| 5662 | if (!hash_unused_entry_key_p (k)) | ||
| 5663 | call2 (function, k, HASH_VALUE (h, i)); | ||
| 5664 | } | ||
| 5665 | |||
| 5666 | return Qnil; | 5659 | return Qnil; |
| 5667 | } | 5660 | } |
| 5668 | 5661 | ||
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, | |||
| 361 | json = json_check (json_object ()); | 361 | json = json_check (json_object ()); |
| 362 | count = SPECPDL_INDEX (); | 362 | count = SPECPDL_INDEX (); |
| 363 | record_unwind_protect_ptr (json_release_object, json); | 363 | record_unwind_protect_ptr (json_release_object, json); |
| 364 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) | 364 | DOHASH (h, i) |
| 365 | { | 365 | { |
| 366 | Lisp_Object key = HASH_KEY (h, i); | 366 | Lisp_Object key = HASH_KEY (h, i); |
| 367 | if (!hash_unused_entry_key_p (key)) | 367 | CHECK_STRING (key); |
| 368 | { | 368 | Lisp_Object ekey = json_encode (key); |
| 369 | CHECK_STRING (key); | 369 | /* We can't specify the length, so the string must be |
| 370 | Lisp_Object ekey = json_encode (key); | 370 | null-terminated. */ |
| 371 | /* We can't specify the length, so the string must be | 371 | check_string_without_embedded_nulls (ekey); |
| 372 | null-terminated. */ | 372 | const char *key_str = SSDATA (ekey); |
| 373 | check_string_without_embedded_nulls (ekey); | 373 | /* Reject duplicate keys. These are possible if the hash |
| 374 | const char *key_str = SSDATA (ekey); | 374 | table test is not `equal'. */ |
| 375 | /* Reject duplicate keys. These are possible if the hash | 375 | if (json_object_get (json, key_str) != NULL) |
| 376 | table test is not `equal'. */ | 376 | wrong_type_argument (Qjson_value_p, lisp); |
| 377 | if (json_object_get (json, key_str) != NULL) | 377 | int status |
| 378 | wrong_type_argument (Qjson_value_p, lisp); | 378 | = json_object_set_new (json, key_str, |
| 379 | int status | 379 | lisp_to_json (HASH_VALUE (h, i), conf)); |
| 380 | = json_object_set_new (json, key_str, | 380 | if (status == -1) |
| 381 | lisp_to_json (HASH_VALUE (h, i), conf)); | 381 | { |
| 382 | if (status == -1) | 382 | /* A failure can be caused either by an invalid key or |
| 383 | { | 383 | by low memory. */ |
| 384 | /* A failure can be caused either by an invalid key or | 384 | json_check_utf8 (ekey); |
| 385 | by low memory. */ | 385 | json_out_of_memory (); |
| 386 | json_check_utf8 (ekey); | 386 | } |
| 387 | json_out_of_memory (); | 387 | } |
| 388 | } | ||
| 389 | } | ||
| 390 | } | ||
| 391 | } | 388 | } |
| 392 | else if (NILP (lisp)) | 389 | else if (NILP (lisp)) |
| 393 | return json_check (json_object ()); | 390 | 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) | |||
| 2579 | return h->test->hashfn (key, h); | 2579 | return h->test->hashfn (key, h); |
| 2580 | } | 2580 | } |
| 2581 | 2581 | ||
| 2582 | /* Hash table iteration construct (roughly an inlined maphash): | ||
| 2583 | Iterate IDXVAR as index over valid entries of TABLE. | ||
| 2584 | The body may remove the current entry or alter its value slot, but not | ||
| 2585 | mutate TABLE in any other way. */ | ||
| 2586 | #define DOHASH(TABLE, IDXVAR) \ | ||
| 2587 | for (ptrdiff_t IDXVAR = 0; IDXVAR < (TABLE)->table_size; IDXVAR++) \ | ||
| 2588 | if (!hash_unused_entry_key_p (HASH_KEY (TABLE, IDXVAR))) | ||
| 2589 | |||
| 2582 | void hash_table_thaw (Lisp_Object hash_table); | 2590 | void hash_table_thaw (Lisp_Object hash_table); |
| 2583 | 2591 | ||
| 2584 | /* Default size for hash tables if not specified. */ | 2592 | /* 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'. */) | |||
| 2114 | goto found_matching_key; | 2114 | goto found_matching_key; |
| 2115 | } | 2115 | } |
| 2116 | else | 2116 | else |
| 2117 | for (i = 0; i < HASH_TABLE_SIZE (h); ++i) | 2117 | DOHASH (h, j) |
| 2118 | { | 2118 | { |
| 2119 | i = j; | ||
| 2119 | tem = HASH_KEY (h, i); | 2120 | tem = HASH_KEY (h, i); |
| 2120 | if (hash_unused_entry_key_p (tem)) continue; | ||
| 2121 | Lisp_Object strkey = (SYMBOLP (tem) ? Fsymbol_name (tem) : tem); | 2121 | Lisp_Object strkey = (SYMBOLP (tem) ? Fsymbol_name (tem) : tem); |
| 2122 | if (!STRINGP (strkey)) continue; | 2122 | if (!STRINGP (strkey)) continue; |
| 2123 | if (BASE_EQ (Fcompare_strings (string, Qnil, Qnil, | 2123 | 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) | |||
| 1285 | { /* Remove unnecessary objects, which appear only once in OBJ; | 1285 | { /* Remove unnecessary objects, which appear only once in OBJ; |
| 1286 | that is, whose status is Qt. */ | 1286 | that is, whose status is Qt. */ |
| 1287 | struct Lisp_Hash_Table *h = XHASH_TABLE (Vprint_number_table); | 1287 | struct Lisp_Hash_Table *h = XHASH_TABLE (Vprint_number_table); |
| 1288 | ptrdiff_t i; | 1288 | DOHASH (h, i) |
| 1289 | 1289 | if (EQ (HASH_VALUE (h, i), Qt)) | |
| 1290 | for (i = 0; i < HASH_TABLE_SIZE (h); ++i) | 1290 | Fremhash (HASH_KEY (h, i), Vprint_number_table); |
| 1291 | { | ||
| 1292 | Lisp_Object key = HASH_KEY (h, i); | ||
| 1293 | if (!hash_unused_entry_key_p (key) | ||
| 1294 | && EQ (HASH_VALUE (h, i), Qt)) | ||
| 1295 | Fremhash (key, Vprint_number_table); | ||
| 1296 | } | ||
| 1297 | } | 1291 | } |
| 1298 | } | 1292 | } |
| 1299 | 1293 | ||