diff options
| author | Mattias EngdegÄrd | 2024-01-19 16:45:51 +0100 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2024-01-21 11:21:51 +0100 |
| commit | 50201e03b9c4133296dbd10e6c7ebd5dc2a62d50 (patch) | |
| tree | 7a703926319f43833c026652c8e669f08eb916a3 /src | |
| parent | 7a87ca09a73d61b46bfcaca317095ce7545bd3f3 (diff) | |
| download | emacs-50201e03b9c4133296dbd10e6c7ebd5dc2a62d50.tar.gz emacs-50201e03b9c4133296dbd10e6c7ebd5dc2a62d50.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fns.c | 45 |
1 files changed, 25 insertions, 20 deletions
| @@ -4462,14 +4462,26 @@ reduce_emacs_uint_to_hash_hash (EMACS_UINT x) | |||
| 4462 | : x ^ (x >> (8 * (sizeof x - sizeof (hash_hash_t))))); | 4462 | : x ^ (x >> (8 * (sizeof x - sizeof (hash_hash_t))))); |
| 4463 | } | 4463 | } |
| 4464 | 4464 | ||
| 4465 | static EMACS_INT | ||
| 4466 | sxhash_eq (Lisp_Object key) | ||
| 4467 | { | ||
| 4468 | if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (key)) | ||
| 4469 | key = SYMBOL_WITH_POS_SYM (key); | ||
| 4470 | return XHASH (key) ^ XTYPE (key); | ||
| 4471 | } | ||
| 4472 | |||
| 4473 | static EMACS_INT | ||
| 4474 | sxhash_eql (Lisp_Object key) | ||
| 4475 | { | ||
| 4476 | return FLOATP (key) || BIGNUMP (key) ? sxhash (key) : sxhash_eq (key); | ||
| 4477 | } | ||
| 4478 | |||
| 4465 | /* Ignore H and return a hash code for KEY which uses 'eq' to compare keys. */ | 4479 | /* Ignore H and return a hash code for KEY which uses 'eq' to compare keys. */ |
| 4466 | 4480 | ||
| 4467 | static hash_hash_t | 4481 | static hash_hash_t |
| 4468 | hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h) | 4482 | hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h) |
| 4469 | { | 4483 | { |
| 4470 | if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (key)) | 4484 | return reduce_emacs_uint_to_hash_hash (sxhash_eq (key)); |
| 4471 | key = SYMBOL_WITH_POS_SYM (key); | ||
| 4472 | return reduce_emacs_uint_to_hash_hash (XHASH (key) ^ XTYPE (key)); | ||
| 4473 | } | 4485 | } |
| 4474 | 4486 | ||
| 4475 | /* Ignore H and return a hash code for KEY which uses 'equal' to | 4487 | /* 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) | |||
| 4484 | static hash_hash_t | 4496 | static hash_hash_t |
| 4485 | hashfn_eql (Lisp_Object key, struct Lisp_Hash_Table *h) | 4497 | hashfn_eql (Lisp_Object key, struct Lisp_Hash_Table *h) |
| 4486 | { | 4498 | { |
| 4487 | return (FLOATP (key) || BIGNUMP (key) | 4499 | return reduce_emacs_uint_to_hash_hash (sxhash_eql (key)); |
| 4488 | ? hashfn_equal (key, h) : hashfn_eq (key, h)); | ||
| 4489 | } | 4500 | } |
| 4490 | 4501 | ||
| 4491 | /* Given H, return a hash code for KEY which uses a user-defined | 4502 | /* Given H, return a hash code for KEY which uses a user-defined |
| @@ -5283,13 +5294,11 @@ collect_interval (INTERVAL interval, void *arg) | |||
| 5283 | Lisp Interface | 5294 | Lisp Interface |
| 5284 | ***********************************************************************/ | 5295 | ***********************************************************************/ |
| 5285 | 5296 | ||
| 5286 | /* Reduce X to a Lisp fixnum. */ | 5297 | /* Reduce the hash value X to a Lisp fixnum. */ |
| 5287 | static inline Lisp_Object | 5298 | static inline Lisp_Object |
| 5288 | hash_hash_to_fixnum (hash_hash_t x) | 5299 | reduce_emacs_uint_to_fixnum (EMACS_UINT x) |
| 5289 | { | 5300 | { |
| 5290 | return make_ufixnum (FIXNUM_BITS < 8 * sizeof x | 5301 | return make_ufixnum (SXHASH_REDUCE (x)); |
| 5291 | ? (x ^ x >> (8 * sizeof x - FIXNUM_BITS)) & INTMASK | ||
| 5292 | : x); | ||
| 5293 | } | 5302 | } |
| 5294 | 5303 | ||
| 5295 | DEFUN ("sxhash-eq", Fsxhash_eq, Ssxhash_eq, 1, 1, 0, | 5304 | 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)). | |||
| 5299 | Hash codes are not guaranteed to be preserved across Emacs sessions. */) | 5308 | Hash codes are not guaranteed to be preserved across Emacs sessions. */) |
| 5300 | (Lisp_Object obj) | 5309 | (Lisp_Object obj) |
| 5301 | { | 5310 | { |
| 5302 | return hash_hash_to_fixnum (hashfn_eq (obj, NULL)); | 5311 | return reduce_emacs_uint_to_fixnum (sxhash_eq (obj)); |
| 5303 | } | 5312 | } |
| 5304 | 5313 | ||
| 5305 | DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0, | 5314 | DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0, |
| @@ -5310,7 +5319,7 @@ isn't necessarily true. | |||
| 5310 | Hash codes are not guaranteed to be preserved across Emacs sessions. */) | 5319 | Hash codes are not guaranteed to be preserved across Emacs sessions. */) |
| 5311 | (Lisp_Object obj) | 5320 | (Lisp_Object obj) |
| 5312 | { | 5321 | { |
| 5313 | return hash_hash_to_fixnum (hashfn_eql (obj, NULL)); | 5322 | return reduce_emacs_uint_to_fixnum (sxhash_eql (obj)); |
| 5314 | } | 5323 | } |
| 5315 | 5324 | ||
| 5316 | DEFUN ("sxhash-equal", Fsxhash_equal, Ssxhash_equal, 1, 1, 0, | 5325 | DEFUN ("sxhash-equal", Fsxhash_equal, Ssxhash_equal, 1, 1, 0, |
| @@ -5321,7 +5330,7 @@ opposite isn't necessarily true. | |||
| 5321 | Hash codes are not guaranteed to be preserved across Emacs sessions. */) | 5330 | Hash codes are not guaranteed to be preserved across Emacs sessions. */) |
| 5322 | (Lisp_Object obj) | 5331 | (Lisp_Object obj) |
| 5323 | { | 5332 | { |
| 5324 | return hash_hash_to_fixnum (hashfn_equal (obj, NULL)); | 5333 | return reduce_emacs_uint_to_fixnum (sxhash (obj)); |
| 5325 | } | 5334 | } |
| 5326 | 5335 | ||
| 5327 | DEFUN ("sxhash-equal-including-properties", Fsxhash_equal_including_properties, | 5336 | DEFUN ("sxhash-equal-including-properties", Fsxhash_equal_including_properties, |
| @@ -5334,14 +5343,10 @@ If (sxhash-equal-including-properties A B), then | |||
| 5334 | Hash codes are not guaranteed to be preserved across Emacs sessions. */) | 5343 | Hash codes are not guaranteed to be preserved across Emacs sessions. */) |
| 5335 | (Lisp_Object obj) | 5344 | (Lisp_Object obj) |
| 5336 | { | 5345 | { |
| 5346 | EMACS_UINT hash = sxhash (obj); | ||
| 5337 | if (STRINGP (obj)) | 5347 | if (STRINGP (obj)) |
| 5338 | { | 5348 | traverse_intervals (string_intervals (obj), 0, hash_interval, &hash); |
| 5339 | EMACS_UINT hash = 0; | 5349 | return reduce_emacs_uint_to_fixnum (hash); |
| 5340 | traverse_intervals (string_intervals (obj), 0, hash_interval, &hash); | ||
| 5341 | return make_ufixnum (SXHASH_REDUCE (sxhash_combine (sxhash (obj), hash))); | ||
| 5342 | } | ||
| 5343 | |||
| 5344 | return hash_hash_to_fixnum (hashfn_equal (obj, NULL)); | ||
| 5345 | } | 5350 | } |
| 5346 | 5351 | ||
| 5347 | 5352 | ||