From f378ed1a0b1ca2ceed5afabcf5f303ae339039ba Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 22 Jul 2019 21:27:33 -0700 Subject: Avoid overexposing fixnums for hash codes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/fns.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/fns.c') 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, enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES }; static bool internal_equal (Lisp_Object, Lisp_Object, enum equal_kind, int, Lisp_Object); +static EMACS_UINT sxhash_bignum (struct Lisp_Bignum *); DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0, doc: /* Return the argument unchanged. */ @@ -4021,7 +4022,8 @@ Lisp_Object hashfn_user_defined (Lisp_Object key, struct Lisp_Hash_Table *h) { Lisp_Object args[] = { h->test.user_hash_function, key }; - return hash_table_user_defined_call (ARRAYELTS (args), args, h); + Lisp_Object hash = hash_table_user_defined_call (ARRAYELTS (args), args, h); + return BIGNUMP (hash) ? make_fixnum (sxhash_bignum (XBIGNUM (hash))) : hash; } struct hash_table_test const @@ -4707,7 +4709,7 @@ sxhash (Lisp_Object obj, int depth) ***********************************************************************/ DEFUN ("sxhash-eq", Fsxhash_eq, Ssxhash_eq, 1, 1, 0, - doc: /* Return a fixnum hash code for OBJ suitable for `eq'. + doc: /* Return an integer hash code for OBJ suitable for `eq'. If (eq A B), then (= (sxhash-eq A) (sxhash-eq B)). Hash 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. */) } DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0, - doc: /* Return a fixnum hash code for OBJ suitable for `eql'. + doc: /* Return an integer hash code for OBJ suitable for `eql'. If (eql A B), then (= (sxhash-eql A) (sxhash-eql B)). Hash 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. */) } DEFUN ("sxhash-equal", Fsxhash_equal, Ssxhash_equal, 1, 1, 0, - doc: /* Return a fixnum hash code for OBJ suitable for `equal'. + doc: /* Return an integer hash code for OBJ suitable for `equal'. If (equal A B), then (= (sxhash-equal A) (sxhash-equal B)). Hash 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 Default is 65. :rehash-size REHASH-SIZE - Indicates how to expand the table when it -fills up. If REHASH-SIZE is a fixnum, increase the size by that +fills up. If REHASH-SIZE is an integer, increase the size by that amount. If it is a float, it must be > 1.0, and the new size is the old size multiplied by that factor. Default is 1.5. -- cgit v1.2.1