Make better use of fixnum range in sxhash etc

Recent hash table changes reduced the range of sxhash, sxhash-eq etc
to [0,2**32) on platforms with 62-bit fixnums.  This change makes them
use the full fixnum range again.  Hash table hashing is unaffected.

* src/fns.c (sxhash_eq, sxhash_eql): New.
(hash_hash_to_fixnum): Replace with...
(reduce_emacs_uint_to_fixnum): ...this.
(hashfn_eq, hashfn_eql, Fsxhash_eq, Fsxhash_eql, Fsxhash_equal)
(Fsxhash_equal_including_properties): Use the new functions.
This commit is contained in:
Mattias Engdegård 2024-01-19 16:45:51 +01:00
parent 7a87ca09a7
commit 50201e03b9

View file

@ -4462,14 +4462,26 @@ reduce_emacs_uint_to_hash_hash (EMACS_UINT x)
: x ^ (x >> (8 * (sizeof x - sizeof (hash_hash_t)))));
}
static EMACS_INT
sxhash_eq (Lisp_Object key)
{
if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (key))
key = SYMBOL_WITH_POS_SYM (key);
return XHASH (key) ^ XTYPE (key);
}
static EMACS_INT
sxhash_eql (Lisp_Object key)
{
return FLOATP (key) || BIGNUMP (key) ? sxhash (key) : sxhash_eq (key);
}
/* Ignore H and return a hash code for KEY which uses 'eq' to compare keys. */
static hash_hash_t
hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h)
{
if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (key))
key = SYMBOL_WITH_POS_SYM (key);
return reduce_emacs_uint_to_hash_hash (XHASH (key) ^ XTYPE (key));
return reduce_emacs_uint_to_hash_hash (sxhash_eq (key));
}
/* Ignore H and return a hash code for KEY which uses 'equal' to
@ -4484,8 +4496,7 @@ hashfn_equal (Lisp_Object key, struct Lisp_Hash_Table *h)
static hash_hash_t
hashfn_eql (Lisp_Object key, struct Lisp_Hash_Table *h)
{
return (FLOATP (key) || BIGNUMP (key)
? hashfn_equal (key, h) : hashfn_eq (key, h));
return reduce_emacs_uint_to_hash_hash (sxhash_eql (key));
}
/* Given H, return a hash code for KEY which uses a user-defined
@ -5283,13 +5294,11 @@ collect_interval (INTERVAL interval, void *arg)
Lisp Interface
***********************************************************************/
/* Reduce X to a Lisp fixnum. */
/* Reduce the hash value X to a Lisp fixnum. */
static inline Lisp_Object
hash_hash_to_fixnum (hash_hash_t x)
reduce_emacs_uint_to_fixnum (EMACS_UINT x)
{
return make_ufixnum (FIXNUM_BITS < 8 * sizeof x
? (x ^ x >> (8 * sizeof x - FIXNUM_BITS)) & INTMASK
: x);
return make_ufixnum (SXHASH_REDUCE (x));
}
DEFUN ("sxhash-eq", Fsxhash_eq, Ssxhash_eq, 1, 1, 0,
@ -5299,7 +5308,7 @@ If (eq A B), then (= (sxhash-eq A) (sxhash-eq B)).
Hash codes are not guaranteed to be preserved across Emacs sessions. */)
(Lisp_Object obj)
{
return hash_hash_to_fixnum (hashfn_eq (obj, NULL));
return reduce_emacs_uint_to_fixnum (sxhash_eq (obj));
}
DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0,
@ -5310,7 +5319,7 @@ isn't necessarily true.
Hash codes are not guaranteed to be preserved across Emacs sessions. */)
(Lisp_Object obj)
{
return hash_hash_to_fixnum (hashfn_eql (obj, NULL));
return reduce_emacs_uint_to_fixnum (sxhash_eql (obj));
}
DEFUN ("sxhash-equal", Fsxhash_equal, Ssxhash_equal, 1, 1, 0,
@ -5321,7 +5330,7 @@ opposite isn't necessarily true.
Hash codes are not guaranteed to be preserved across Emacs sessions. */)
(Lisp_Object obj)
{
return hash_hash_to_fixnum (hashfn_equal (obj, NULL));
return reduce_emacs_uint_to_fixnum (sxhash (obj));
}
DEFUN ("sxhash-equal-including-properties", Fsxhash_equal_including_properties,
@ -5334,14 +5343,10 @@ If (sxhash-equal-including-properties A B), then
Hash codes are not guaranteed to be preserved across Emacs sessions. */)
(Lisp_Object obj)
{
EMACS_UINT hash = sxhash (obj);
if (STRINGP (obj))
{
EMACS_UINT hash = 0;
traverse_intervals (string_intervals (obj), 0, hash_interval, &hash);
return make_ufixnum (SXHASH_REDUCE (sxhash_combine (sxhash (obj), hash)));
}
return hash_hash_to_fixnum (hashfn_equal (obj, NULL));
traverse_intervals (string_intervals (obj), 0, hash_interval, &hash);
return reduce_emacs_uint_to_fixnum (hash);
}