aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2019-07-22 21:27:33 -0700
committerPaul Eggert2019-07-22 21:28:18 -0700
commitf378ed1a0b1ca2ceed5afabcf5f303ae339039ba (patch)
tree767e994477690e2681cb7fe027af7d708efd6cc6 /src
parent97477edaf2044e51696f46b166b43801893156a3 (diff)
downloademacs-f378ed1a0b1ca2ceed5afabcf5f303ae339039ba.tar.gz
emacs-f378ed1a0b1ca2ceed5afabcf5f303ae339039ba.zip
Avoid overexposing fixnums for hash codes
Following a suggestion by Stefan Monnier in: https://lists.gnu.org/r/emacs-devel/2019-07/msg00530.html * doc/lispref/hash.texi (Creating Hash, Defining Hash): * src/fns.c (Fsxhash_eq, Fsxhash_eql, Fsxhash_equal, Fmake_hash_table): Don’t insist that hash codes be fixnums, reverting the recent doc changes to the contrary. * src/bytecode.c (exec_byte_code): Special-case only the eq case, as the others aren’t worth tuning now that we treat bignum hashes like fixnums. * src/fns.c (hashfn_user_defined): If the hash code is a bignum, reduce its hash down to a fixnum.
Diffstat (limited to 'src')
-rw-r--r--src/bytecode.c14
-rw-r--r--src/fns.c12
2 files changed, 11 insertions, 15 deletions
diff --git a/src/bytecode.c b/src/bytecode.c
index d668a9a6a15..9aad1eb642b 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -1406,18 +1406,12 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
1406 1406
1407 /* h->count is a faster approximation for HASH_TABLE_SIZE (h) 1407 /* h->count is a faster approximation for HASH_TABLE_SIZE (h)
1408 here. */ 1408 here. */
1409 if (h->count <= 5) 1409 if (h->count <= 5 && !h->test.cmpfn)
1410 { /* Do a linear search if there are not many cases 1410 { /* Do a linear search if there are not many cases
1411 FIXME: 5 is arbitrarily chosen. */ 1411 FIXME: 5 is arbitrarily chosen. */
1412 Lisp_Object hash_code 1412 for (i = h->count; 0 <= --i; )
1413 = h->test.cmpfn ? h->test.hashfn (v1, h) : Qnil; 1413 if (EQ (v1, HASH_KEY (h, i)))
1414 1414 break;
1415 for (i = h->count; 0 <= --i; )
1416 if (EQ (v1, HASH_KEY (h, i))
1417 || (h->test.cmpfn
1418 && EQ (hash_code, HASH_HASH (h, i))
1419 && !NILP (h->test.cmpfn (v1, HASH_KEY (h, i), h))))
1420 break;
1421 } 1415 }
1422 else 1416 else
1423 i = hash_lookup (h, v1, NULL); 1417 i = hash_lookup (h, v1, NULL);
diff --git a/src/fns.c b/src/fns.c
index 734a2e253c7..d28d437df9c 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -47,6 +47,7 @@ static void sort_vector_copy (Lisp_Object, ptrdiff_t,
47enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES }; 47enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES };
48static bool internal_equal (Lisp_Object, Lisp_Object, 48static bool internal_equal (Lisp_Object, Lisp_Object,
49 enum equal_kind, int, Lisp_Object); 49 enum equal_kind, int, Lisp_Object);
50static EMACS_UINT sxhash_bignum (struct Lisp_Bignum *);
50 51
51DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0, 52DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
52 doc: /* Return the argument unchanged. */ 53 doc: /* Return the argument unchanged. */
@@ -4021,7 +4022,8 @@ Lisp_Object
4021hashfn_user_defined (Lisp_Object key, struct Lisp_Hash_Table *h) 4022hashfn_user_defined (Lisp_Object key, struct Lisp_Hash_Table *h)
4022{ 4023{
4023 Lisp_Object args[] = { h->test.user_hash_function, key }; 4024 Lisp_Object args[] = { h->test.user_hash_function, key };
4024 return hash_table_user_defined_call (ARRAYELTS (args), args, h); 4025 Lisp_Object hash = hash_table_user_defined_call (ARRAYELTS (args), args, h);
4026 return BIGNUMP (hash) ? make_fixnum (sxhash_bignum (XBIGNUM (hash))) : hash;
4025} 4027}
4026 4028
4027struct hash_table_test const 4029struct hash_table_test const
@@ -4707,7 +4709,7 @@ sxhash (Lisp_Object obj, int depth)
4707 ***********************************************************************/ 4709 ***********************************************************************/
4708 4710
4709DEFUN ("sxhash-eq", Fsxhash_eq, Ssxhash_eq, 1, 1, 0, 4711DEFUN ("sxhash-eq", Fsxhash_eq, Ssxhash_eq, 1, 1, 0,
4710 doc: /* Return a fixnum hash code for OBJ suitable for `eq'. 4712 doc: /* Return an integer hash code for OBJ suitable for `eq'.
4711If (eq A B), then (= (sxhash-eq A) (sxhash-eq B)). 4713If (eq A B), then (= (sxhash-eq A) (sxhash-eq B)).
4712 4714
4713Hash codes are not guaranteed to be preserved across Emacs sessions. */) 4715Hash codes are not guaranteed to be preserved across Emacs sessions. */)
@@ -4717,7 +4719,7 @@ Hash codes are not guaranteed to be preserved across Emacs sessions. */)
4717} 4719}
4718 4720
4719DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0, 4721DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0,
4720 doc: /* Return a fixnum hash code for OBJ suitable for `eql'. 4722 doc: /* Return an integer hash code for OBJ suitable for `eql'.
4721If (eql A B), then (= (sxhash-eql A) (sxhash-eql B)). 4723If (eql A B), then (= (sxhash-eql A) (sxhash-eql B)).
4722 4724
4723Hash codes are not guaranteed to be preserved across Emacs sessions. */) 4725Hash codes are not guaranteed to be preserved across Emacs sessions. */)
@@ -4727,7 +4729,7 @@ Hash codes are not guaranteed to be preserved across Emacs sessions. */)
4727} 4729}
4728 4730
4729DEFUN ("sxhash-equal", Fsxhash_equal, Ssxhash_equal, 1, 1, 0, 4731DEFUN ("sxhash-equal", Fsxhash_equal, Ssxhash_equal, 1, 1, 0,
4730 doc: /* Return a fixnum hash code for OBJ suitable for `equal'. 4732 doc: /* Return an integer hash code for OBJ suitable for `equal'.
4731If (equal A B), then (= (sxhash-equal A) (sxhash-equal B)). 4733If (equal A B), then (= (sxhash-equal A) (sxhash-equal B)).
4732 4734
4733Hash codes are not guaranteed to be preserved across Emacs sessions. */) 4735Hash codes are not guaranteed to be preserved across Emacs sessions. */)
@@ -4751,7 +4753,7 @@ keys. Default is `eql'. Predefined are the tests `eq', `eql', and
4751Default is 65. 4753Default is 65.
4752 4754
4753:rehash-size REHASH-SIZE - Indicates how to expand the table when it 4755:rehash-size REHASH-SIZE - Indicates how to expand the table when it
4754fills up. If REHASH-SIZE is a fixnum, increase the size by that 4756fills up. If REHASH-SIZE is an integer, increase the size by that
4755amount. If it is a float, it must be > 1.0, and the new size is the 4757amount. If it is a float, it must be > 1.0, and the new size is the
4756old size multiplied by that factor. Default is 1.5. 4758old size multiplied by that factor. Default is 1.5.
4757 4759