aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattias EngdegÄrd2023-11-22 14:54:34 +0100
committerMattias EngdegÄrd2024-01-13 20:50:39 +0100
commit1998039f7a8f2ecc884a6fed85c0cc1ce06f83e2 (patch)
tree92fb11cd22e2560e637c95cc61c42eff7edfa7d0 /src
parent11e467eb6004286765c1d8c408f8d773d9113aca (diff)
downloademacs-1998039f7a8f2ecc884a6fed85c0cc1ce06f83e2.tar.gz
emacs-1998039f7a8f2ecc884a6fed85c0cc1ce06f83e2.zip
Change hash_hash_t to uint32_t
This saves a lot of memory and is quite sufficient. Hash functions are adapted to produce a hash_hash_t eventually, which eliminates some useless and information-destroying intermediate hash reduction steps. We still use EMACS_UINT for most of the actual hashing steps before producing the final value; this may be slightly wasteful on 32-bit platforms with 64-bit EMACS_UINT. * src/lisp.h (hash_hash_t): Change to uint32_t. * src/fns.c (reduce_emacs_uint_to_hash_hash): New. (hashfn_eq, hashfn_equal, hashfn_user_defined): Reduce return values to hash_hash_t. (sxhash_string): Remove. Caller changed to hash_string. (sxhash_float, sxhash_list, sxhash_vector, sxhash_bool_vector) (sxhash_bignum): Remove wasteful calls to SXHASH_REDUCE. (hash_hash_to_fixnum): New. (Fsxhash_eq, Fsxhash_eql, Fsxhash_equal) (Fsxhash_equal_including_properties): Convert return values to fixnum.
Diffstat (limited to 'src')
-rw-r--r--src/fns.c77
-rw-r--r--src/lisp.h2
2 files changed, 43 insertions, 36 deletions
diff --git a/src/fns.c b/src/fns.c
index ed7b7bb2024..3765fc74967 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -4452,6 +4452,16 @@ cmpfn_user_defined (Lisp_Object key1, Lisp_Object key2,
4452 return hash_table_user_defined_call (ARRAYELTS (args), args, h); 4452 return hash_table_user_defined_call (ARRAYELTS (args), args, h);
4453} 4453}
4454 4454
4455/* Reduce an EMACS_UINT hash value to hash_hash_t. */
4456static inline hash_hash_t
4457reduce_emacs_uint_to_hash_hash (EMACS_UINT x)
4458{
4459 verify (sizeof x <= 2 * sizeof (hash_hash_t));
4460 return (sizeof x == sizeof (hash_hash_t)
4461 ? x
4462 : x ^ (x >> (8 * (sizeof x - sizeof (hash_hash_t)))));
4463}
4464
4455/* Ignore H and return a hash code for KEY which uses 'eq' to compare keys. */ 4465/* Ignore H and return a hash code for KEY which uses 'eq' to compare keys. */
4456 4466
4457static hash_hash_t 4467static hash_hash_t
@@ -4459,21 +4469,18 @@ hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h)
4459{ 4469{
4460 if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (key)) 4470 if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (key))
4461 key = SYMBOL_WITH_POS_SYM (key); 4471 key = SYMBOL_WITH_POS_SYM (key);
4462 return XHASH (key) ^ XTYPE (key); 4472 return reduce_emacs_uint_to_hash_hash (XHASH (key) ^ XTYPE (key));
4463} 4473}
4464 4474
4465/* Ignore H and return a hash code for KEY which uses 'equal' to compare keys. 4475/* Ignore H and return a hash code for KEY which uses 'equal' to
4466 The hash code is at most INTMASK. */ 4476 compare keys. */
4467
4468static hash_hash_t 4477static hash_hash_t
4469hashfn_equal (Lisp_Object key, struct Lisp_Hash_Table *h) 4478hashfn_equal (Lisp_Object key, struct Lisp_Hash_Table *h)
4470{ 4479{
4471 return sxhash (key); 4480 return reduce_emacs_uint_to_hash_hash (sxhash (key));
4472} 4481}
4473 4482
4474/* Ignore H and return a hash code for KEY which uses 'eql' to compare keys. 4483/* Ignore H and return a hash code for KEY which uses 'eql' to compare keys. */
4475 The hash code is at most INTMASK. */
4476
4477static hash_hash_t 4484static hash_hash_t
4478hashfn_eql (Lisp_Object key, struct Lisp_Hash_Table *h) 4485hashfn_eql (Lisp_Object key, struct Lisp_Hash_Table *h)
4479{ 4486{
@@ -4489,7 +4496,8 @@ hashfn_user_defined (Lisp_Object key, struct Lisp_Hash_Table *h)
4489{ 4496{
4490 Lisp_Object args[] = { h->test->user_hash_function, key }; 4497 Lisp_Object args[] = { h->test->user_hash_function, key };
4491 Lisp_Object hash = hash_table_user_defined_call (ARRAYELTS (args), args, h); 4498 Lisp_Object hash = hash_table_user_defined_call (ARRAYELTS (args), args, h);
4492 return FIXNUMP (hash) ? XUFIXNUM(hash) : sxhash (hash); 4499 return reduce_emacs_uint_to_hash_hash (FIXNUMP (hash)
4500 ? XUFIXNUM(hash) : sxhash (hash));
4493} 4501}
4494 4502
4495struct hash_table_test const 4503struct hash_table_test const
@@ -5061,16 +5069,6 @@ hash_string (char const *ptr, ptrdiff_t len)
5061 return hash; 5069 return hash;
5062} 5070}
5063 5071
5064/* Return a hash for string PTR which has length LEN. The hash
5065 code returned is at most INTMASK. */
5066
5067static EMACS_UINT
5068sxhash_string (char const *ptr, ptrdiff_t len)
5069{
5070 EMACS_UINT hash = hash_string (ptr, len);
5071 return SXHASH_REDUCE (hash);
5072}
5073
5074/* Return a hash for the floating point value VAL. */ 5072/* Return a hash for the floating point value VAL. */
5075 5073
5076static EMACS_UINT 5074static EMACS_UINT
@@ -5080,7 +5078,7 @@ sxhash_float (double val)
5080 union double_and_words u = { .val = val }; 5078 union double_and_words u = { .val = val };
5081 for (int i = 0; i < WORDS_PER_DOUBLE; i++) 5079 for (int i = 0; i < WORDS_PER_DOUBLE; i++)
5082 hash = sxhash_combine (hash, u.word[i]); 5080 hash = sxhash_combine (hash, u.word[i]);
5083 return SXHASH_REDUCE (hash); 5081 return hash;
5084} 5082}
5085 5083
5086/* Return a hash for list LIST. DEPTH is the current depth in the 5084/* Return a hash for list LIST. DEPTH is the current depth in the
@@ -5107,7 +5105,7 @@ sxhash_list (Lisp_Object list, int depth)
5107 hash = sxhash_combine (hash, hash2); 5105 hash = sxhash_combine (hash, hash2);
5108 } 5106 }
5109 5107
5110 return SXHASH_REDUCE (hash); 5108 return hash;
5111} 5109}
5112 5110
5113 5111
@@ -5127,7 +5125,7 @@ sxhash_vector (Lisp_Object vec, int depth)
5127 hash = sxhash_combine (hash, hash2); 5125 hash = sxhash_combine (hash, hash2);
5128 } 5126 }
5129 5127
5130 return SXHASH_REDUCE (hash); 5128 return hash;
5131} 5129}
5132 5130
5133/* Return a hash for bool-vector VECTOR. */ 5131/* Return a hash for bool-vector VECTOR. */
@@ -5143,7 +5141,7 @@ sxhash_bool_vector (Lisp_Object vec)
5143 for (i = 0; i < n; ++i) 5141 for (i = 0; i < n; ++i)
5144 hash = sxhash_combine (hash, bool_vector_data (vec)[i]); 5142 hash = sxhash_combine (hash, bool_vector_data (vec)[i]);
5145 5143
5146 return SXHASH_REDUCE (hash); 5144 return hash;
5147} 5145}
5148 5146
5149/* Return a hash for a bignum. */ 5147/* Return a hash for a bignum. */
@@ -5158,19 +5156,18 @@ sxhash_bignum (Lisp_Object bignum)
5158 for (i = 0; i < nlimbs; ++i) 5156 for (i = 0; i < nlimbs; ++i)
5159 hash = sxhash_combine (hash, mpz_getlimbn (*n, i)); 5157 hash = sxhash_combine (hash, mpz_getlimbn (*n, i));
5160 5158
5161 return SXHASH_REDUCE (hash); 5159 return hash;
5162} 5160}
5163 5161
5164
5165/* Return a hash code for OBJ. DEPTH is the current depth in the Lisp
5166 structure. Value is an unsigned integer clipped to INTMASK. */
5167
5168EMACS_UINT 5162EMACS_UINT
5169sxhash (Lisp_Object obj) 5163sxhash (Lisp_Object obj)
5170{ 5164{
5171 return sxhash_obj (obj, 0); 5165 return sxhash_obj (obj, 0);
5172} 5166}
5173 5167
5168/* Return a hash code for OBJ. DEPTH is the current depth in the Lisp
5169 structure. */
5170
5174static EMACS_UINT 5171static EMACS_UINT
5175sxhash_obj (Lisp_Object obj, int depth) 5172sxhash_obj (Lisp_Object obj, int depth)
5176{ 5173{
@@ -5186,7 +5183,7 @@ sxhash_obj (Lisp_Object obj, int depth)
5186 return XHASH (obj); 5183 return XHASH (obj);
5187 5184
5188 case Lisp_String: 5185 case Lisp_String:
5189 return sxhash_string (SSDATA (obj), SBYTES (obj)); 5186 return hash_string (SSDATA (obj), SBYTES (obj));
5190 5187
5191 case Lisp_Vectorlike: 5188 case Lisp_Vectorlike:
5192 { 5189 {
@@ -5213,7 +5210,7 @@ sxhash_obj (Lisp_Object obj, int depth)
5213 = XMARKER (obj)->buffer ? XMARKER (obj)->bytepos : 0; 5210 = XMARKER (obj)->buffer ? XMARKER (obj)->bytepos : 0;
5214 EMACS_UINT hash 5211 EMACS_UINT hash
5215 = sxhash_combine ((intptr_t) XMARKER (obj)->buffer, bytepos); 5212 = sxhash_combine ((intptr_t) XMARKER (obj)->buffer, bytepos);
5216 return SXHASH_REDUCE (hash); 5213 return hash;
5217 } 5214 }
5218 else if (pvec_type == PVEC_BOOL_VECTOR) 5215 else if (pvec_type == PVEC_BOOL_VECTOR)
5219 return sxhash_bool_vector (obj); 5216 return sxhash_bool_vector (obj);
@@ -5222,7 +5219,7 @@ sxhash_obj (Lisp_Object obj, int depth)
5222 EMACS_UINT hash = OVERLAY_START (obj); 5219 EMACS_UINT hash = OVERLAY_START (obj);
5223 hash = sxhash_combine (hash, OVERLAY_END (obj)); 5220 hash = sxhash_combine (hash, OVERLAY_END (obj));
5224 hash = sxhash_combine (hash, sxhash_obj (XOVERLAY (obj)->plist, depth)); 5221 hash = sxhash_combine (hash, sxhash_obj (XOVERLAY (obj)->plist, depth));
5225 return SXHASH_REDUCE (hash); 5222 return hash;
5226 } 5223 }
5227 else if (symbols_with_pos_enabled && pvec_type == PVEC_SYMBOL_WITH_POS) 5224 else if (symbols_with_pos_enabled && pvec_type == PVEC_SYMBOL_WITH_POS)
5228 return sxhash_obj (XSYMBOL_WITH_POS (obj)->sym, depth + 1); 5225 return sxhash_obj (XSYMBOL_WITH_POS (obj)->sym, depth + 1);
@@ -5258,6 +5255,15 @@ collect_interval (INTERVAL interval, Lisp_Object collector)
5258 Lisp Interface 5255 Lisp Interface
5259 ***********************************************************************/ 5256 ***********************************************************************/
5260 5257
5258/* Reduce X to a Lisp fixnum. */
5259static inline Lisp_Object
5260hash_hash_to_fixnum (hash_hash_t x)
5261{
5262 return make_ufixnum (FIXNUM_BITS < 8 * sizeof x
5263 ? (x ^ x >> (8 * sizeof x - FIXNUM_BITS)) & INTMASK
5264 : x);
5265}
5266
5261DEFUN ("sxhash-eq", Fsxhash_eq, Ssxhash_eq, 1, 1, 0, 5267DEFUN ("sxhash-eq", Fsxhash_eq, Ssxhash_eq, 1, 1, 0,
5262 doc: /* Return an integer hash code for OBJ suitable for `eq'. 5268 doc: /* Return an integer hash code for OBJ suitable for `eq'.
5263If (eq A B), then (= (sxhash-eq A) (sxhash-eq B)). 5269If (eq A B), then (= (sxhash-eq A) (sxhash-eq B)).
@@ -5265,7 +5271,7 @@ If (eq A B), then (= (sxhash-eq A) (sxhash-eq B)).
5265Hash codes are not guaranteed to be preserved across Emacs sessions. */) 5271Hash codes are not guaranteed to be preserved across Emacs sessions. */)
5266 (Lisp_Object obj) 5272 (Lisp_Object obj)
5267{ 5273{
5268 return make_ufixnum (hashfn_eq (obj, NULL)); 5274 return hash_hash_to_fixnum (hashfn_eq (obj, NULL));
5269} 5275}
5270 5276
5271DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0, 5277DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0,
@@ -5276,7 +5282,7 @@ isn't necessarily true.
5276Hash codes are not guaranteed to be preserved across Emacs sessions. */) 5282Hash codes are not guaranteed to be preserved across Emacs sessions. */)
5277 (Lisp_Object obj) 5283 (Lisp_Object obj)
5278{ 5284{
5279 return make_ufixnum (hashfn_eql (obj, NULL)); 5285 return hash_hash_to_fixnum (hashfn_eql (obj, NULL));
5280} 5286}
5281 5287
5282DEFUN ("sxhash-equal", Fsxhash_equal, Ssxhash_equal, 1, 1, 0, 5288DEFUN ("sxhash-equal", Fsxhash_equal, Ssxhash_equal, 1, 1, 0,
@@ -5287,7 +5293,7 @@ opposite isn't necessarily true.
5287Hash codes are not guaranteed to be preserved across Emacs sessions. */) 5293Hash codes are not guaranteed to be preserved across Emacs sessions. */)
5288 (Lisp_Object obj) 5294 (Lisp_Object obj)
5289{ 5295{
5290 return make_ufixnum (hashfn_equal (obj, NULL)); 5296 return hash_hash_to_fixnum (hashfn_equal (obj, NULL));
5291} 5297}
5292 5298
5293DEFUN ("sxhash-equal-including-properties", Fsxhash_equal_including_properties, 5299DEFUN ("sxhash-equal-including-properties", Fsxhash_equal_including_properties,
@@ -5302,6 +5308,7 @@ Hash codes are not guaranteed to be preserved across Emacs sessions. */)
5302{ 5308{
5303 if (STRINGP (obj)) 5309 if (STRINGP (obj))
5304 { 5310 {
5311 /* FIXME: This is very wasteful. We needn't cons at all. */
5305 Lisp_Object collector = Fcons (Qnil, Qnil); 5312 Lisp_Object collector = Fcons (Qnil, Qnil);
5306 traverse_intervals (string_intervals (obj), 0, collect_interval, 5313 traverse_intervals (string_intervals (obj), 0, collect_interval,
5307 collector); 5314 collector);
@@ -5311,7 +5318,7 @@ Hash codes are not guaranteed to be preserved across Emacs sessions. */)
5311 sxhash (CDR (collector))))); 5318 sxhash (CDR (collector)))));
5312 } 5319 }
5313 5320
5314 return make_ufixnum (hashfn_equal (obj, NULL)); 5321 return hash_hash_to_fixnum (hashfn_equal (obj, NULL));
5315} 5322}
5316 5323
5317 5324
diff --git a/src/lisp.h b/src/lisp.h
index 0701028c14c..64492361e64 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2387,7 +2387,7 @@ struct Lisp_Hash_Table;
2387 2387
2388/* The type of a hash value stored in the table. 2388/* The type of a hash value stored in the table.
2389 It's unsigned and a subtype of EMACS_UINT. */ 2389 It's unsigned and a subtype of EMACS_UINT. */
2390typedef EMACS_UINT hash_hash_t; 2390typedef uint32_t hash_hash_t;
2391 2391
2392typedef enum { 2392typedef enum {
2393 Test_eql, 2393 Test_eql,