aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattias EngdegÄrd2023-10-29 11:57:06 +0100
committerMattias EngdegÄrd2024-01-13 20:50:38 +0100
commita3ae5653cfe1ab2b3eb4c77ce729844ad442b562 (patch)
tree660892925e71fc631389825b8bf729b5c604f730 /src
parentfa5c07fc87d557e642fc325852e8d0c87a9c176e (diff)
downloademacs-a3ae5653cfe1ab2b3eb4c77ce729844ad442b562.tar.gz
emacs-a3ae5653cfe1ab2b3eb4c77ce729844ad442b562.zip
Store hash values as integers instead of Lisp_Object
This improves typing, saves pointless tagging and untagging, and prepares for further changes. The new typedef hash_hash_t is an alias for EMACS_UINT, and hash values are still limited to the fixnum range. We now use hash_unused instead of Qnil to mark unused entries. * src/lisp.h (hash_hash_t): New typedef for EMACS_UINT. (hash_unused): New constant. (struct hash_table_test): `hashfn` now returns hash_hash_t. All callers and implementations changed. (struct Lisp_Hash_Table): Retype hash vector to an array of hash_hash_t. All code using it changed accordingly. (HASH_HASH, hash_from_key): * src/fns.c (set_hash_index_slot, hash_index_index) (hash_lookup_with_hash, hash_lookup_get_hash, hash_put): (hash_lookup, hash_put): Retype hash value arguments and return values. All callers adapted.
Diffstat (limited to 'src')
-rw-r--r--src/category.c2
-rw-r--r--src/charset.c2
-rw-r--r--src/composite.c5
-rw-r--r--src/emacs-module.c3
-rw-r--r--src/fns.c74
-rw-r--r--src/image.c3
-rw-r--r--src/json.c3
-rw-r--r--src/lisp.h25
-rw-r--r--src/lread.c8
-rw-r--r--src/macfont.m5
-rw-r--r--src/pdumper.c2
11 files changed, 75 insertions, 57 deletions
diff --git a/src/category.c b/src/category.c
index 583cdb3eebb..e7fbf1ff500 100644
--- a/src/category.c
+++ b/src/category.c
@@ -53,7 +53,7 @@ hash_get_category_set (Lisp_Object table, Lisp_Object category_set)
53 (table, 1, 53 (table, 1,
54 make_hash_table (hashtest_equal, DEFAULT_HASH_SIZE, Weak_None, false)); 54 make_hash_table (hashtest_equal, DEFAULT_HASH_SIZE, Weak_None, false));
55 struct Lisp_Hash_Table *h = XHASH_TABLE (XCHAR_TABLE (table)->extras[1]); 55 struct Lisp_Hash_Table *h = XHASH_TABLE (XCHAR_TABLE (table)->extras[1]);
56 Lisp_Object hash; 56 hash_hash_t hash;
57 ptrdiff_t i = hash_lookup (h, category_set, &hash); 57 ptrdiff_t i = hash_lookup (h, category_set, &hash);
58 if (i >= 0) 58 if (i >= 0)
59 return HASH_KEY (h, i); 59 return HASH_KEY (h, i);
diff --git a/src/charset.c b/src/charset.c
index 3aa105e57bd..add3bf846f8 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -850,7 +850,6 @@ usage: (define-charset-internal ...) */)
850 /* Charset attr vector. */ 850 /* Charset attr vector. */
851 Lisp_Object attrs; 851 Lisp_Object attrs;
852 Lisp_Object val; 852 Lisp_Object val;
853 Lisp_Object hash_code;
854 struct Lisp_Hash_Table *hash_table = XHASH_TABLE (Vcharset_hash_table); 853 struct Lisp_Hash_Table *hash_table = XHASH_TABLE (Vcharset_hash_table);
855 int i, j; 854 int i, j;
856 struct charset charset; 855 struct charset charset;
@@ -1108,6 +1107,7 @@ usage: (define-charset-internal ...) */)
1108 CHECK_LIST (args[charset_arg_plist]); 1107 CHECK_LIST (args[charset_arg_plist]);
1109 ASET (attrs, charset_plist, args[charset_arg_plist]); 1108 ASET (attrs, charset_plist, args[charset_arg_plist]);
1110 1109
1110 hash_hash_t hash_code;
1111 charset.hash_index = hash_lookup (hash_table, args[charset_arg_name], 1111 charset.hash_index = hash_lookup (hash_table, args[charset_arg_name],
1112 &hash_code); 1112 &hash_code);
1113 if (charset.hash_index >= 0) 1113 if (charset.hash_index >= 0)
diff --git a/src/composite.c b/src/composite.c
index ed1aeb380a0..bd69a953e3f 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -166,7 +166,7 @@ ptrdiff_t
166get_composition_id (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t nchars, 166get_composition_id (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t nchars,
167 Lisp_Object prop, Lisp_Object string) 167 Lisp_Object prop, Lisp_Object string)
168{ 168{
169 Lisp_Object id, length, components, key, *key_contents, hash_code; 169 Lisp_Object id, length, components, key, *key_contents;
170 ptrdiff_t glyph_len; 170 ptrdiff_t glyph_len;
171 struct Lisp_Hash_Table *hash_table = XHASH_TABLE (composition_hash_table); 171 struct Lisp_Hash_Table *hash_table = XHASH_TABLE (composition_hash_table);
172 ptrdiff_t hash_index; 172 ptrdiff_t hash_index;
@@ -240,6 +240,7 @@ get_composition_id (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t nchars,
240 else 240 else
241 goto invalid_composition; 241 goto invalid_composition;
242 242
243 hash_hash_t hash_code;
243 hash_index = hash_lookup (hash_table, key, &hash_code); 244 hash_index = hash_lookup (hash_table, key, &hash_code);
244 if (hash_index >= 0) 245 if (hash_index >= 0)
245 { 246 {
@@ -653,7 +654,7 @@ composition_gstring_put_cache (Lisp_Object gstring, ptrdiff_t len)
653{ 654{
654 struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); 655 struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
655 Lisp_Object header = LGSTRING_HEADER (gstring); 656 Lisp_Object header = LGSTRING_HEADER (gstring);
656 Lisp_Object hash = hash_from_key (h, header); 657 EMACS_UINT hash = hash_from_key (h, header);
657 if (len < 0) 658 if (len < 0)
658 { 659 {
659 ptrdiff_t glyph_len = LGSTRING_GLYPH_LEN (gstring); 660 ptrdiff_t glyph_len = LGSTRING_GLYPH_LEN (gstring);
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 60aed68f2cd..728da8c2882 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -427,7 +427,8 @@ module_make_global_ref (emacs_env *env, emacs_value value)
427{ 427{
428 MODULE_FUNCTION_BEGIN (NULL); 428 MODULE_FUNCTION_BEGIN (NULL);
429 struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash); 429 struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
430 Lisp_Object new_obj = value_to_lisp (value), hashcode; 430 Lisp_Object new_obj = value_to_lisp (value);
431 hash_hash_t hashcode;
431 ptrdiff_t i = hash_lookup (h, new_obj, &hashcode); 432 ptrdiff_t i = hash_lookup (h, new_obj, &hashcode);
432 433
433 /* Note: This approach requires the garbage collector to never move 434 /* Note: This approach requires the garbage collector to never move
diff --git a/src/fns.c b/src/fns.c
index 3aca588a8a5..5a3c51c8412 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2759,7 +2759,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
2759 case Lisp_Cons: case Lisp_Vectorlike: 2759 case Lisp_Cons: case Lisp_Vectorlike:
2760 { 2760 {
2761 struct Lisp_Hash_Table *h = XHASH_TABLE (ht); 2761 struct Lisp_Hash_Table *h = XHASH_TABLE (ht);
2762 Lisp_Object hash; 2762 hash_hash_t hash;
2763 ptrdiff_t i = hash_lookup (h, o1, &hash); 2763 ptrdiff_t i = hash_lookup (h, o1, &hash);
2764 if (i >= 0) 2764 if (i >= 0)
2765 { /* `o1' was seen already. */ 2765 { /* `o1' was seen already. */
@@ -4279,7 +4279,7 @@ set_hash_next_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, ptrdiff_t val)
4279 h->next[idx] = val; 4279 h->next[idx] = val;
4280} 4280}
4281static void 4281static void
4282set_hash_hash_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val) 4282set_hash_hash_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, hash_hash_t val)
4283{ 4283{
4284 eassert (idx >= 0 && idx < h->table_size); 4284 eassert (idx >= 0 && idx < h->table_size);
4285 h->hash[idx] = val; 4285 h->hash[idx] = val;
@@ -4450,41 +4450,42 @@ cmpfn_user_defined (Lisp_Object key1, Lisp_Object key2,
4450 4450
4451/* Ignore H and return a hash code for KEY which uses 'eq' to compare keys. */ 4451/* Ignore H and return a hash code for KEY which uses 'eq' to compare keys. */
4452 4452
4453static Lisp_Object 4453static hash_hash_t
4454hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h) 4454hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h)
4455{ 4455{
4456 if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (key)) 4456 if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (key))
4457 key = SYMBOL_WITH_POS_SYM (key); 4457 key = SYMBOL_WITH_POS_SYM (key);
4458 return make_ufixnum (XHASH (key) ^ XTYPE (key)); 4458 return XHASH (key) ^ XTYPE (key);
4459} 4459}
4460 4460
4461/* Ignore H and return a hash code for KEY which uses 'equal' to compare keys. 4461/* Ignore H and return a hash code for KEY which uses 'equal' to compare keys.
4462 The hash code is at most INTMASK. */ 4462 The hash code is at most INTMASK. */
4463 4463
4464static Lisp_Object 4464static hash_hash_t
4465hashfn_equal (Lisp_Object key, struct Lisp_Hash_Table *h) 4465hashfn_equal (Lisp_Object key, struct Lisp_Hash_Table *h)
4466{ 4466{
4467 return make_ufixnum (sxhash (key)); 4467 return sxhash (key);
4468} 4468}
4469 4469
4470/* Ignore H and return a hash code for KEY which uses 'eql' to compare keys. 4470/* Ignore H and return a hash code for KEY which uses 'eql' to compare keys.
4471 The hash code is at most INTMASK. */ 4471 The hash code is at most INTMASK. */
4472 4472
4473static Lisp_Object 4473static hash_hash_t
4474hashfn_eql (Lisp_Object key, struct Lisp_Hash_Table *h) 4474hashfn_eql (Lisp_Object key, struct Lisp_Hash_Table *h)
4475{ 4475{
4476 return (FLOATP (key) || BIGNUMP (key) ? hashfn_equal : hashfn_eq) (key, h); 4476 return (FLOATP (key) || BIGNUMP (key)
4477 ? hashfn_equal (key, h) : hashfn_eq (key, h));
4477} 4478}
4478 4479
4479/* Given H, return a hash code for KEY which uses a user-defined 4480/* Given H, return a hash code for KEY which uses a user-defined
4480 function to compare keys. */ 4481 function to compare keys. */
4481 4482
4482static Lisp_Object 4483static hash_hash_t
4483hashfn_user_defined (Lisp_Object key, struct Lisp_Hash_Table *h) 4484hashfn_user_defined (Lisp_Object key, struct Lisp_Hash_Table *h)
4484{ 4485{
4485 Lisp_Object args[] = { h->test.user_hash_function, key }; 4486 Lisp_Object args[] = { h->test.user_hash_function, key };
4486 Lisp_Object hash = hash_table_user_defined_call (ARRAYELTS (args), args, h); 4487 Lisp_Object hash = hash_table_user_defined_call (ARRAYELTS (args), args, h);
4487 return FIXNUMP (hash) ? hash : make_ufixnum (sxhash (hash)); 4488 return FIXNUMP (hash) ? XUFIXNUM(hash) : sxhash (hash);
4488} 4489}
4489 4490
4490struct hash_table_test const 4491struct hash_table_test const
@@ -4584,7 +4585,8 @@ make_hash_table (struct hash_table_test test, EMACS_INT size,
4584 h->key_and_value[i] = HASH_UNUSED_ENTRY_KEY; 4585 h->key_and_value[i] = HASH_UNUSED_ENTRY_KEY;
4585 4586
4586 h->hash = hash_table_alloc_bytes (size * sizeof *h->hash); 4587 h->hash = hash_table_alloc_bytes (size * sizeof *h->hash);
4587 memclear (h->hash, size * sizeof *h->hash); 4588 for (ptrdiff_t i = 0; i < size; i++)
4589 h->hash[i] = hash_unused;
4588 4590
4589 h->next = hash_table_alloc_bytes (size * sizeof *h->next); 4591 h->next = hash_table_alloc_bytes (size * sizeof *h->next);
4590 for (ptrdiff_t i = 0; i < size - 1; i++) 4592 for (ptrdiff_t i = 0; i < size - 1; i++)
@@ -4650,10 +4652,10 @@ copy_hash_table (struct Lisp_Hash_Table *h1)
4650 4652
4651/* Compute index into the index vector from a hash value. */ 4653/* Compute index into the index vector from a hash value. */
4652static inline ptrdiff_t 4654static inline ptrdiff_t
4653hash_index_index (struct Lisp_Hash_Table *h, Lisp_Object hash_code) 4655hash_index_index (struct Lisp_Hash_Table *h, hash_hash_t hash)
4654{ 4656{
4655 eassert (h->index_size > 0); 4657 eassert (h->index_size > 0);
4656 return XUFIXNUM (hash_code) % h->index_size; 4658 return hash % h->index_size;
4657} 4659}
4658 4660
4659/* Resize hash table H if it's too full. If H cannot be resized 4661/* Resize hash table H if it's too full. If H cannot be resized
@@ -4690,9 +4692,10 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
4690 for (ptrdiff_t i = 2 * old_size; i < 2 * new_size; i++) 4692 for (ptrdiff_t i = 2 * old_size; i < 2 * new_size; i++)
4691 key_and_value[i] = HASH_UNUSED_ENTRY_KEY; 4693 key_and_value[i] = HASH_UNUSED_ENTRY_KEY;
4692 4694
4693 Lisp_Object *hash = hash_table_alloc_bytes (new_size * sizeof *hash); 4695 hash_hash_t *hash = hash_table_alloc_bytes (new_size * sizeof *hash);
4694 memcpy (hash, h->hash, old_size * sizeof *hash); 4696 memcpy (hash, h->hash, old_size * sizeof *hash);
4695 memclear (hash + old_size, (new_size - old_size) * word_size); 4697 for (ptrdiff_t i = old_size; i < new_size; i++)
4698 hash[i] = hash_unused;
4696 4699
4697 ptrdiff_t old_index_size = h->index_size; 4700 ptrdiff_t old_index_size = h->index_size;
4698 ptrdiff_t index_size = hash_index_size (new_size); 4701 ptrdiff_t index_size = hash_index_size (new_size);
@@ -4723,7 +4726,7 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
4723 /* Rehash: all data occupy entries 0..old_size-1. */ 4726 /* Rehash: all data occupy entries 0..old_size-1. */
4724 for (ptrdiff_t i = 0; i < old_size; i++) 4727 for (ptrdiff_t i = 0; i < old_size; i++)
4725 { 4728 {
4726 Lisp_Object hash_code = HASH_HASH (h, i); 4729 hash_hash_t hash_code = HASH_HASH (h, i);
4727 ptrdiff_t start_of_bucket = hash_index_index (h, hash_code); 4730 ptrdiff_t start_of_bucket = hash_index_index (h, hash_code);
4728 set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket)); 4731 set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket));
4729 set_hash_index_slot (h, start_of_bucket, i); 4732 set_hash_index_slot (h, start_of_bucket, i);
@@ -4764,7 +4767,8 @@ hash_table_thaw (Lisp_Object hash_table)
4764 h->next_free = -1; 4767 h->next_free = -1;
4765 4768
4766 h->hash = hash_table_alloc_bytes (size * sizeof *h->hash); 4769 h->hash = hash_table_alloc_bytes (size * sizeof *h->hash);
4767 memclear (h->hash, size * sizeof *h->hash); 4770 for (ptrdiff_t i = 0; i < size; i++)
4771 h->hash[i] = hash_unused;
4768 4772
4769 h->next = hash_table_alloc_bytes (size * sizeof *h->next); 4773 h->next = hash_table_alloc_bytes (size * sizeof *h->next);
4770 for (ptrdiff_t i = 0; i < size; i++) 4774 for (ptrdiff_t i = 0; i < size; i++)
@@ -4779,7 +4783,7 @@ hash_table_thaw (Lisp_Object hash_table)
4779 for (ptrdiff_t i = 0; i < size; i++) 4783 for (ptrdiff_t i = 0; i < size; i++)
4780 { 4784 {
4781 Lisp_Object key = HASH_KEY (h, i); 4785 Lisp_Object key = HASH_KEY (h, i);
4782 Lisp_Object hash_code = hash_from_key (h, key); 4786 hash_hash_t hash_code = hash_from_key (h, key);
4783 ptrdiff_t start_of_bucket = hash_index_index (h, hash_code); 4787 ptrdiff_t start_of_bucket = hash_index_index (h, hash_code);
4784 set_hash_hash_slot (h, i, hash_code); 4788 set_hash_hash_slot (h, i, hash_code);
4785 set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket)); 4789 set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket));
@@ -4792,9 +4796,9 @@ hash_table_thaw (Lisp_Object hash_table)
4792 matching KEY, or -1 if not found. */ 4796 matching KEY, or -1 if not found. */
4793 4797
4794ptrdiff_t 4798ptrdiff_t
4795hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object *hash) 4799hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, hash_hash_t *hash)
4796{ 4800{
4797 Lisp_Object hash_code = hash_from_key (h, key); 4801 hash_hash_t hash_code = hash_from_key (h, key);
4798 if (hash) 4802 if (hash)
4799 *hash = hash_code; 4803 *hash = hash_code;
4800 4804
@@ -4803,7 +4807,7 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object *hash)
4803 for (i = HASH_INDEX (h, start_of_bucket); 0 <= i; i = HASH_NEXT (h, i)) 4807 for (i = HASH_INDEX (h, start_of_bucket); 0 <= i; i = HASH_NEXT (h, i))
4804 if (EQ (key, HASH_KEY (h, i)) 4808 if (EQ (key, HASH_KEY (h, i))
4805 || (h->test.cmpfn 4809 || (h->test.cmpfn
4806 && EQ (hash_code, HASH_HASH (h, i)) 4810 && hash_code == HASH_HASH (h, i)
4807 && !NILP (h->test.cmpfn (key, HASH_KEY (h, i), h)))) 4811 && !NILP (h->test.cmpfn (key, HASH_KEY (h, i), h))))
4808 break; 4812 break;
4809 4813
@@ -4824,7 +4828,7 @@ check_mutable_hash_table (Lisp_Object obj, struct Lisp_Hash_Table *h)
4824 4828
4825ptrdiff_t 4829ptrdiff_t
4826hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value, 4830hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value,
4827 Lisp_Object hash) 4831 hash_hash_t hash)
4828{ 4832{
4829 /* Increment count after resizing because resizing may fail. */ 4833 /* Increment count after resizing because resizing may fail. */
4830 maybe_resize_hash_table (h); 4834 maybe_resize_hash_table (h);
@@ -4832,7 +4836,7 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value,
4832 4836
4833 /* Store key/value in the key_and_value vector. */ 4837 /* Store key/value in the key_and_value vector. */
4834 ptrdiff_t i = h->next_free; 4838 ptrdiff_t i = h->next_free;
4835 eassert (NILP (HASH_HASH (h, i))); 4839 eassert (HASH_HASH (h, i) == hash_unused);
4836 eassert (hash_unused_entry_key_p (HASH_KEY (h, i))); 4840 eassert (hash_unused_entry_key_p (HASH_KEY (h, i)));
4837 h->next_free = HASH_NEXT (h, i); 4841 h->next_free = HASH_NEXT (h, i);
4838 set_hash_key_slot (h, i, key); 4842 set_hash_key_slot (h, i, key);
@@ -4854,8 +4858,8 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value,
4854void 4858void
4855hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key) 4859hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key)
4856{ 4860{
4857 Lisp_Object hash_code = hash_from_key (h, key); 4861 hash_hash_t hashval = hash_from_key (h, key);
4858 ptrdiff_t start_of_bucket = hash_index_index (h, hash_code); 4862 ptrdiff_t start_of_bucket = hash_index_index (h, hashval);
4859 ptrdiff_t prev = -1; 4863 ptrdiff_t prev = -1;
4860 4864
4861 for (ptrdiff_t i = HASH_INDEX (h, start_of_bucket); 4865 for (ptrdiff_t i = HASH_INDEX (h, start_of_bucket);
@@ -4864,7 +4868,7 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key)
4864 { 4868 {
4865 if (EQ (key, HASH_KEY (h, i)) 4869 if (EQ (key, HASH_KEY (h, i))
4866 || (h->test.cmpfn 4870 || (h->test.cmpfn
4867 && EQ (hash_code, HASH_HASH (h, i)) 4871 && hashval == HASH_HASH (h, i)
4868 && !NILP (h->test.cmpfn (key, HASH_KEY (h, i), h)))) 4872 && !NILP (h->test.cmpfn (key, HASH_KEY (h, i), h))))
4869 { 4873 {
4870 /* Take entry out of collision chain. */ 4874 /* Take entry out of collision chain. */
@@ -4877,7 +4881,7 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key)
4877 the free list. */ 4881 the free list. */
4878 set_hash_key_slot (h, i, HASH_UNUSED_ENTRY_KEY); 4882 set_hash_key_slot (h, i, HASH_UNUSED_ENTRY_KEY);
4879 set_hash_value_slot (h, i, Qnil); 4883 set_hash_value_slot (h, i, Qnil);
4880 set_hash_hash_slot (h, i, Qnil); 4884 set_hash_hash_slot (h, i, hash_unused);
4881 set_hash_next_slot (h, i, h->next_free); 4885 set_hash_next_slot (h, i, h->next_free);
4882 h->next_free = i; 4886 h->next_free = i;
4883 h->count--; 4887 h->count--;
@@ -4898,9 +4902,9 @@ hash_clear (struct Lisp_Hash_Table *h)
4898 if (h->count > 0) 4902 if (h->count > 0)
4899 { 4903 {
4900 ptrdiff_t size = HASH_TABLE_SIZE (h); 4904 ptrdiff_t size = HASH_TABLE_SIZE (h);
4901 memclear (h->hash, size * word_size);
4902 for (ptrdiff_t i = 0; i < size; i++) 4905 for (ptrdiff_t i = 0; i < size; i++)
4903 { 4906 {
4907 set_hash_hash_slot (h, i, hash_unused);
4904 set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1); 4908 set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1);
4905 set_hash_key_slot (h, i, HASH_UNUSED_ENTRY_KEY); 4909 set_hash_key_slot (h, i, HASH_UNUSED_ENTRY_KEY);
4906 set_hash_value_slot (h, i, Qnil); 4910 set_hash_value_slot (h, i, Qnil);
@@ -4983,7 +4987,7 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p)
4983 /* Clear key, value, and hash. */ 4987 /* Clear key, value, and hash. */
4984 set_hash_key_slot (h, i, HASH_UNUSED_ENTRY_KEY); 4988 set_hash_key_slot (h, i, HASH_UNUSED_ENTRY_KEY);
4985 set_hash_value_slot (h, i, Qnil); 4989 set_hash_value_slot (h, i, Qnil);
4986 set_hash_hash_slot (h, i, Qnil); 4990 set_hash_hash_slot (h, i, hash_unused);
4987 4991
4988 eassert (h->count != 0); 4992 eassert (h->count != 0);
4989 h->count--; 4993 h->count--;
@@ -5269,7 +5273,7 @@ If (eq A B), then (= (sxhash-eq A) (sxhash-eq B)).
5269Hash codes are not guaranteed to be preserved across Emacs sessions. */) 5273Hash codes are not guaranteed to be preserved across Emacs sessions. */)
5270 (Lisp_Object obj) 5274 (Lisp_Object obj)
5271{ 5275{
5272 return hashfn_eq (obj, NULL); 5276 return make_ufixnum (hashfn_eq (obj, NULL));
5273} 5277}
5274 5278
5275DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0, 5279DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0,
@@ -5280,7 +5284,7 @@ isn't necessarily true.
5280Hash codes are not guaranteed to be preserved across Emacs sessions. */) 5284Hash codes are not guaranteed to be preserved across Emacs sessions. */)
5281 (Lisp_Object obj) 5285 (Lisp_Object obj)
5282{ 5286{
5283 return hashfn_eql (obj, NULL); 5287 return make_ufixnum (hashfn_eql (obj, NULL));
5284} 5288}
5285 5289
5286DEFUN ("sxhash-equal", Fsxhash_equal, Ssxhash_equal, 1, 1, 0, 5290DEFUN ("sxhash-equal", Fsxhash_equal, Ssxhash_equal, 1, 1, 0,
@@ -5291,7 +5295,7 @@ opposite isn't necessarily true.
5291Hash codes are not guaranteed to be preserved across Emacs sessions. */) 5295Hash codes are not guaranteed to be preserved across Emacs sessions. */)
5292 (Lisp_Object obj) 5296 (Lisp_Object obj)
5293{ 5297{
5294 return hashfn_equal (obj, NULL); 5298 return make_ufixnum (hashfn_equal (obj, NULL));
5295} 5299}
5296 5300
5297DEFUN ("sxhash-equal-including-properties", Fsxhash_equal_including_properties, 5301DEFUN ("sxhash-equal-including-properties", Fsxhash_equal_including_properties,
@@ -5315,7 +5319,7 @@ Hash codes are not guaranteed to be preserved across Emacs sessions. */)
5315 sxhash (CDR (collector))))); 5319 sxhash (CDR (collector)))));
5316 } 5320 }
5317 5321
5318 return hashfn_equal (obj, NULL); 5322 return make_ufixnum (hashfn_equal (obj, NULL));
5319} 5323}
5320 5324
5321DEFUN ("make-hash-table", Fmake_hash_table, Smake_hash_table, 0, MANY, 0, 5325DEFUN ("make-hash-table", Fmake_hash_table, Smake_hash_table, 0, MANY, 0,
@@ -5549,7 +5553,7 @@ VALUE. In any case, return VALUE. */)
5549 struct Lisp_Hash_Table *h = check_hash_table (table); 5553 struct Lisp_Hash_Table *h = check_hash_table (table);
5550 check_mutable_hash_table (table, h); 5554 check_mutable_hash_table (table, h);
5551 5555
5552 Lisp_Object hash; 5556 EMACS_UINT hash;
5553 ptrdiff_t i = hash_lookup (h, key, &hash); 5557 ptrdiff_t i = hash_lookup (h, key, &hash);
5554 if (i >= 0) 5558 if (i >= 0)
5555 set_hash_value_slot (h, i, value); 5559 set_hash_value_slot (h, i, value);
@@ -5650,7 +5654,7 @@ Internal use only. */)
5650 { 5654 {
5651 Lisp_Object bucket = Qnil; 5655 Lisp_Object bucket = Qnil;
5652 for (ptrdiff_t j = HASH_INDEX (h, i); j != -1; j = HASH_NEXT (h, j)) 5656 for (ptrdiff_t j = HASH_INDEX (h, i); j != -1; j = HASH_NEXT (h, j))
5653 bucket = Fcons (Fcons (HASH_KEY (h, j), HASH_HASH (h, j)), 5657 bucket = Fcons (Fcons (HASH_KEY (h, j), make_int (HASH_HASH (h, j))),
5654 bucket); 5658 bucket);
5655 if (!NILP (bucket)) 5659 if (!NILP (bucket))
5656 ret = Fcons (Fnreverse (bucket), ret); 5660 ret = Fcons (Fnreverse (bucket), ret);
diff --git a/src/image.c b/src/image.c
index 9c100213590..55b027d568b 100644
--- a/src/image.c
+++ b/src/image.c
@@ -6079,8 +6079,9 @@ xpm_put_color_table_h (Lisp_Object color_table,
6079 Lisp_Object color) 6079 Lisp_Object color)
6080{ 6080{
6081 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table); 6081 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
6082 Lisp_Object chars = make_unibyte_string (chars_start, chars_len), hash_code; 6082 Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
6083 6083
6084 hash_hash_t hash_code;
6084 hash_lookup (table, chars, &hash_code); 6085 hash_lookup (table, chars, &hash_code);
6085 hash_put (table, chars, color, hash_code); 6086 hash_put (table, chars, color, hash_code);
6086} 6087}
diff --git a/src/json.c b/src/json.c
index d98b312ecc9..1bea4baa8ba 100644
--- a/src/json.c
+++ b/src/json.c
@@ -879,7 +879,8 @@ json_to_lisp (json_t *json, const struct json_configuration *conf)
879 json_t *value; 879 json_t *value;
880 json_object_foreach (json, key_str, value) 880 json_object_foreach (json, key_str, value)
881 { 881 {
882 Lisp_Object key = build_string_from_utf8 (key_str), hash; 882 Lisp_Object key = build_string_from_utf8 (key_str);
883 hash_hash_t hash;
883 ptrdiff_t i = hash_lookup (h, key, &hash); 884 ptrdiff_t i = hash_lookup (h, key, &hash);
884 /* Keys in JSON objects are unique, so the key can't 885 /* Keys in JSON objects are unique, so the key can't
885 be present yet. */ 886 be present yet. */
diff --git a/src/lisp.h b/src/lisp.h
index dd457392cca..474498094c9 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2385,6 +2385,10 @@ INLINE int
2385 2385
2386struct Lisp_Hash_Table; 2386struct Lisp_Hash_Table;
2387 2387
2388/* The type of a hash value stored in the table.
2389 It's unsigned and a subtype of EMACS_UINT. */
2390typedef EMACS_UINT hash_hash_t;
2391
2388typedef enum { 2392typedef enum {
2389 Test_eql, 2393 Test_eql,
2390 Test_eq, 2394 Test_eq,
@@ -2406,7 +2410,7 @@ struct hash_table_test
2406 Lisp_Object (*cmpfn) (Lisp_Object, Lisp_Object, struct Lisp_Hash_Table *); 2410 Lisp_Object (*cmpfn) (Lisp_Object, Lisp_Object, struct Lisp_Hash_Table *);
2407 2411
2408 /* C function to compute hash code. */ 2412 /* C function to compute hash code. */
2409 Lisp_Object (*hashfn) (Lisp_Object, struct Lisp_Hash_Table *); 2413 hash_hash_t (*hashfn) (Lisp_Object, struct Lisp_Hash_Table *);
2410}; 2414};
2411 2415
2412typedef enum { 2416typedef enum {
@@ -2421,6 +2425,11 @@ typedef enum {
2421 both key and value remain. */ 2425 both key and value remain. */
2422} hash_table_weakness_t; 2426} hash_table_weakness_t;
2423 2427
2428/* An value that marks an unused hash entry.
2429 Any hash_hash_t value that is not a valid fixnum will do here. */
2430enum { hash_unused = (hash_hash_t)MOST_POSITIVE_FIXNUM + 1 };
2431verify (FIXNUM_OVERFLOW_P (hash_unused));
2432
2424struct Lisp_Hash_Table 2433struct Lisp_Hash_Table
2425{ 2434{
2426 union vectorlike_header header; 2435 union vectorlike_header header;
@@ -2462,9 +2471,9 @@ struct Lisp_Hash_Table
2462 2471
2463 ptrdiff_t table_size; /* Size of the next and hash vectors. */ 2472 ptrdiff_t table_size; /* Size of the next and hash vectors. */
2464 2473
2465 /* Vector of hash codes. Each entry is either a fixnum, or nil if unused. 2474 /* Vector of hash codes. The value hash_unused marks an unused table entry.
2466 This vector is table_size entries long. */ 2475 This vector is table_size entries long. */
2467 Lisp_Object *hash; 2476 hash_hash_t *hash;
2468 2477
2469 /* Vector used to chain entries. If entry I is free, next[I] is the 2478 /* Vector used to chain entries. If entry I is free, next[I] is the
2470 entry number of the next free item. If entry I is non-free, 2479 entry number of the next free item. If entry I is non-free,
@@ -2553,7 +2562,7 @@ HASH_VALUE (const struct Lisp_Hash_Table *h, ptrdiff_t idx)
2553} 2562}
2554 2563
2555/* Value is the hash code computed for entry IDX in hash table H. */ 2564/* Value is the hash code computed for entry IDX in hash table H. */
2556INLINE Lisp_Object 2565INLINE hash_hash_t
2557HASH_HASH (const struct Lisp_Hash_Table *h, ptrdiff_t idx) 2566HASH_HASH (const struct Lisp_Hash_Table *h, ptrdiff_t idx)
2558{ 2567{
2559 eassert (idx >= 0 && idx < h->table_size); 2568 eassert (idx >= 0 && idx < h->table_size);
@@ -2567,8 +2576,8 @@ HASH_TABLE_SIZE (const struct Lisp_Hash_Table *h)
2567 return h->table_size; 2576 return h->table_size;
2568} 2577}
2569 2578
2570/* Compute hash value for KEY in hash table H. */ 2579/* Hash value for KEY in hash table H. */
2571INLINE Lisp_Object 2580INLINE hash_hash_t
2572hash_from_key (struct Lisp_Hash_Table *h, Lisp_Object key) 2581hash_from_key (struct Lisp_Hash_Table *h, Lisp_Object key)
2573{ 2582{
2574 return h->test.hashfn (key, h); 2583 return h->test.hashfn (key, h);
@@ -4054,9 +4063,9 @@ EMACS_UINT sxhash (Lisp_Object);
4054Lisp_Object make_hash_table (struct hash_table_test, EMACS_INT, 4063Lisp_Object make_hash_table (struct hash_table_test, EMACS_INT,
4055 hash_table_weakness_t, bool); 4064 hash_table_weakness_t, bool);
4056Lisp_Object hash_table_weakness_symbol (hash_table_weakness_t weak); 4065Lisp_Object hash_table_weakness_symbol (hash_table_weakness_t weak);
4057ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object *); 4066ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, hash_hash_t *);
4058ptrdiff_t hash_put (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object, 4067ptrdiff_t hash_put (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object,
4059 Lisp_Object); 4068 hash_hash_t);
4060void hash_remove_from_table (struct Lisp_Hash_Table *, Lisp_Object); 4069void hash_remove_from_table (struct Lisp_Hash_Table *, Lisp_Object);
4061extern struct hash_table_test const hashtest_eq, hashtest_eql, hashtest_equal; 4070extern struct hash_table_test const hashtest_eq, hashtest_eql, hashtest_equal;
4062extern void validate_subarray (Lisp_Object, Lisp_Object, Lisp_Object, 4071extern void validate_subarray (Lisp_Object, Lisp_Object, Lisp_Object,
diff --git a/src/lread.c b/src/lread.c
index 284536fc81f..9ad4d35c0c2 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -4255,7 +4255,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4255 struct Lisp_Hash_Table *h 4255 struct Lisp_Hash_Table *h
4256 = XHASH_TABLE (read_objects_map); 4256 = XHASH_TABLE (read_objects_map);
4257 Lisp_Object number = make_fixnum (n); 4257 Lisp_Object number = make_fixnum (n);
4258 Lisp_Object hash; 4258 hash_hash_t hash;
4259 ptrdiff_t i = hash_lookup (h, number, &hash); 4259 ptrdiff_t i = hash_lookup (h, number, &hash);
4260 if (i >= 0) 4260 if (i >= 0)
4261 /* Not normal, but input could be malformed. */ 4261 /* Not normal, but input could be malformed. */
@@ -4571,7 +4571,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4571 4571
4572 struct Lisp_Hash_Table *h2 4572 struct Lisp_Hash_Table *h2
4573 = XHASH_TABLE (read_objects_completed); 4573 = XHASH_TABLE (read_objects_completed);
4574 Lisp_Object hash; 4574 hash_hash_t hash;
4575 ptrdiff_t i = hash_lookup (h2, placeholder, &hash); 4575 ptrdiff_t i = hash_lookup (h2, placeholder, &hash);
4576 eassert (i < 0); 4576 eassert (i < 0);
4577 hash_put (h2, placeholder, Qnil, hash); 4577 hash_put (h2, placeholder, Qnil, hash);
@@ -4586,7 +4586,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4586 { 4586 {
4587 struct Lisp_Hash_Table *h2 4587 struct Lisp_Hash_Table *h2
4588 = XHASH_TABLE (read_objects_completed); 4588 = XHASH_TABLE (read_objects_completed);
4589 Lisp_Object hash; 4589 hash_hash_t hash;
4590 ptrdiff_t i = hash_lookup (h2, obj, &hash); 4590 ptrdiff_t i = hash_lookup (h2, obj, &hash);
4591 eassert (i < 0); 4591 eassert (i < 0);
4592 hash_put (h2, obj, Qnil, hash); 4592 hash_put (h2, obj, Qnil, hash);
@@ -4598,7 +4598,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4598 4598
4599 /* ...and #n# will use the real value from now on. */ 4599 /* ...and #n# will use the real value from now on. */
4600 struct Lisp_Hash_Table *h = XHASH_TABLE (read_objects_map); 4600 struct Lisp_Hash_Table *h = XHASH_TABLE (read_objects_map);
4601 Lisp_Object hash; 4601 hash_hash_t hash;
4602 ptrdiff_t i = hash_lookup (h, e->u.numbered.number, &hash); 4602 ptrdiff_t i = hash_lookup (h, e->u.numbered.number, &hash);
4603 eassert (i >= 0); 4603 eassert (i >= 0);
4604 set_hash_value_slot (h, i, obj); 4604 set_hash_value_slot (h, i, obj);
diff --git a/src/macfont.m b/src/macfont.m
index 8aba440d196..dcaa85bea05 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -980,7 +980,7 @@ macfont_invalidate_family_cache (void)
980 ptrdiff_t i, size = HASH_TABLE_SIZE (h); 980 ptrdiff_t i, size = HASH_TABLE_SIZE (h);
981 981
982 for (i = 0; i < size; ++i) 982 for (i = 0; i < size; ++i)
983 if (!NILP (HASH_HASH (h, i))) 983 if (HASH_HASH (h, i) != hash_unused)
984 { 984 {
985 Lisp_Object value = HASH_VALUE (h, i); 985 Lisp_Object value = HASH_VALUE (h, i);
986 986
@@ -1017,12 +1017,13 @@ macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
1017{ 1017{
1018 struct Lisp_Hash_Table *h; 1018 struct Lisp_Hash_Table *h;
1019 ptrdiff_t i; 1019 ptrdiff_t i;
1020 Lisp_Object hash, value; 1020 Lisp_Object value;
1021 1021
1022 if (!HASH_TABLE_P (macfont_family_cache)) 1022 if (!HASH_TABLE_P (macfont_family_cache))
1023 macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq); 1023 macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
1024 1024
1025 h = XHASH_TABLE (macfont_family_cache); 1025 h = XHASH_TABLE (macfont_family_cache);
1026 hash_hash_t hash;
1026 i = hash_lookup (h, symbol, &hash); 1027 i = hash_lookup (h, symbol, &hash);
1027 value = string ? make_mint_ptr ((void *) CFRetain (string)) : Qnil; 1028 value = string ? make_mint_ptr ((void *) CFRetain (string)) : Qnil;
1028 if (i >= 0) 1029 if (i >= 0)
diff --git a/src/pdumper.c b/src/pdumper.c
index 8a93c45e07b..5ed91c668df 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2661,7 +2661,7 @@ hash_table_contents (struct Lisp_Hash_Table *h)
2661 relies on it by expecting hash table indices to stay constant 2661 relies on it by expecting hash table indices to stay constant
2662 across the dump. */ 2662 across the dump. */
2663 for (ptrdiff_t i = 0; i < old_size; i++) 2663 for (ptrdiff_t i = 0; i < old_size; i++)
2664 if (!NILP (HASH_HASH (h, i))) 2664 if (HASH_HASH (h, i) != hash_unused)
2665 { 2665 {
2666 key_and_value[n++] = HASH_KEY (h, i); 2666 key_and_value[n++] = HASH_KEY (h, i);
2667 key_and_value[n++] = HASH_VALUE (h, i); 2667 key_and_value[n++] = HASH_VALUE (h, i);