diff options
| author | Paul Eggert | 2019-07-20 19:40:03 -0700 |
|---|---|---|
| committer | Paul Eggert | 2019-07-20 20:13:46 -0700 |
| commit | 515afc9c15870cd7bd6b96e2d8b89938116923ac (patch) | |
| tree | e57bf126a8e6076edb1c4fa87e4908c94fd8d779 /src | |
| parent | b6f194a0fb6dbd1b19aa01f95a955f5b8b23b40e (diff) | |
| download | emacs-515afc9c15870cd7bd6b96e2d8b89938116923ac.tar.gz emacs-515afc9c15870cd7bd6b96e2d8b89938116923ac.zip | |
Fix crash if user test munges hash table
* src/fns.c (restore_mutability)
(hash_table_user_defined_call): New functions.
(cmpfn_user_defined, hashfn_user_defined): Use them.
(make_hash_table, copy_hash_table):
Mark new hash table as mutable.
(check_mutable_hash_table): New function.
(Fclrhash, Fputhash, Fremhash): Use it instead of CHECK_IMPURE.
* src/lisp.h (struct hash_table_test): User-defined functions
now take pointers to struct Lisp_Hash_Table, not to struct
hash_table_test. All uses changed.
(struct Lisp_Hash_Table): New member ‘mutable’.
* src/pdumper.c (dump_hash_table): Copy it.
* test/src/fns-tests.el (test-hash-function-that-mutates-hash-table):
New test, which tests for the bug.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 1 | ||||
| -rw-r--r-- | src/bytecode.c | 5 | ||||
| -rw-r--r-- | src/composite.c | 2 | ||||
| -rw-r--r-- | src/fns.c | 74 | ||||
| -rw-r--r-- | src/lisp.h | 15 | ||||
| -rw-r--r-- | src/pdumper.c | 1 | ||||
| -rw-r--r-- | src/profiler.c | 8 |
7 files changed, 75 insertions, 31 deletions
diff --git a/src/alloc.c b/src/alloc.c index 09b3a4ea7e4..1718ce0fafc 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -5352,6 +5352,7 @@ purecopy_hash_table (struct Lisp_Hash_Table *table) | |||
| 5352 | pure->count = table->count; | 5352 | pure->count = table->count; |
| 5353 | pure->next_free = table->next_free; | 5353 | pure->next_free = table->next_free; |
| 5354 | pure->purecopy = table->purecopy; | 5354 | pure->purecopy = table->purecopy; |
| 5355 | eassert (!pure->mutable); | ||
| 5355 | pure->rehash_threshold = table->rehash_threshold; | 5356 | pure->rehash_threshold = table->rehash_threshold; |
| 5356 | pure->rehash_size = table->rehash_size; | 5357 | pure->rehash_size = table->rehash_size; |
| 5357 | pure->key_and_value = purecopy (table->key_and_value); | 5358 | pure->key_and_value = purecopy (table->key_and_value); |
diff --git a/src/bytecode.c b/src/bytecode.c index e82de026a82..d668a9a6a15 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -1410,14 +1410,13 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 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 | Lisp_Object hash_code |
| 1413 | = h->test.cmpfn ? h->test.hashfn (v1, &h->test) : Qnil; | 1413 | = h->test.cmpfn ? h->test.hashfn (v1, h) : Qnil; |
| 1414 | 1414 | ||
| 1415 | for (i = h->count; 0 <= --i; ) | 1415 | for (i = h->count; 0 <= --i; ) |
| 1416 | if (EQ (v1, HASH_KEY (h, i)) | 1416 | if (EQ (v1, HASH_KEY (h, i)) |
| 1417 | || (h->test.cmpfn | 1417 | || (h->test.cmpfn |
| 1418 | && EQ (hash_code, HASH_HASH (h, i)) | 1418 | && EQ (hash_code, HASH_HASH (h, i)) |
| 1419 | && !NILP (h->test.cmpfn (v1, HASH_KEY (h, i), | 1419 | && !NILP (h->test.cmpfn (v1, HASH_KEY (h, i), h)))) |
| 1420 | &h->test)))) | ||
| 1421 | break; | 1420 | break; |
| 1422 | } | 1421 | } |
| 1423 | else | 1422 | else |
diff --git a/src/composite.c b/src/composite.c index c36663f8e97..a6606d5fc45 100644 --- a/src/composite.c +++ b/src/composite.c | |||
| @@ -655,7 +655,7 @@ composition_gstring_put_cache (Lisp_Object gstring, ptrdiff_t len) | |||
| 655 | struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); | 655 | struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); |
| 656 | hash_rehash_if_needed (h); | 656 | hash_rehash_if_needed (h); |
| 657 | Lisp_Object header = LGSTRING_HEADER (gstring); | 657 | Lisp_Object header = LGSTRING_HEADER (gstring); |
| 658 | Lisp_Object hash = h->test.hashfn (header, &h->test); | 658 | Lisp_Object hash = h->test.hashfn (header, h); |
| 659 | if (len < 0) | 659 | if (len < 0) |
| 660 | { | 660 | { |
| 661 | ptrdiff_t glyph_len = LGSTRING_GLYPH_LEN (gstring); | 661 | ptrdiff_t glyph_len = LGSTRING_GLYPH_LEN (gstring); |
| @@ -3931,11 +3931,37 @@ HASH_INDEX (struct Lisp_Hash_Table *h, ptrdiff_t idx) | |||
| 3931 | return XFIXNUM (AREF (h->index, idx)); | 3931 | return XFIXNUM (AREF (h->index, idx)); |
| 3932 | } | 3932 | } |
| 3933 | 3933 | ||
| 3934 | /* Restore a hash table's mutability after the critical section exits. */ | ||
| 3935 | |||
| 3936 | static void | ||
| 3937 | restore_mutability (void *ptr) | ||
| 3938 | { | ||
| 3939 | struct Lisp_Hash_Table *h = ptr; | ||
| 3940 | h->mutable = true; | ||
| 3941 | } | ||
| 3942 | |||
| 3943 | /* Return the result of calling a user-defined hash or comparison | ||
| 3944 | function ARGS[0] with arguments ARGS[1] through ARGS[NARGS - 1]. | ||
| 3945 | Signal an error if the function attempts to modify H, which | ||
| 3946 | otherwise might lead to undefined behavior. */ | ||
| 3947 | |||
| 3948 | static Lisp_Object | ||
| 3949 | hash_table_user_defined_call (ptrdiff_t nargs, Lisp_Object *args, | ||
| 3950 | struct Lisp_Hash_Table *h) | ||
| 3951 | { | ||
| 3952 | if (!h->mutable) | ||
| 3953 | return Ffuncall (nargs, args); | ||
| 3954 | ptrdiff_t count = inhibit_garbage_collection (); | ||
| 3955 | record_unwind_protect_ptr (restore_mutability, h); | ||
| 3956 | h->mutable = false; | ||
| 3957 | return unbind_to (count, Ffuncall (nargs, args)); | ||
| 3958 | } | ||
| 3959 | |||
| 3934 | /* Ignore HT and compare KEY1 and KEY2 using 'eql'. | 3960 | /* Ignore HT and compare KEY1 and KEY2 using 'eql'. |
| 3935 | Value is true if KEY1 and KEY2 are the same. */ | 3961 | Value is true if KEY1 and KEY2 are the same. */ |
| 3936 | 3962 | ||
| 3937 | static Lisp_Object | 3963 | static Lisp_Object |
| 3938 | cmpfn_eql (Lisp_Object key1, Lisp_Object key2, struct hash_table_test *ht) | 3964 | cmpfn_eql (Lisp_Object key1, Lisp_Object key2, struct Lisp_Hash_Table *h) |
| 3939 | { | 3965 | { |
| 3940 | return Feql (key1, key2); | 3966 | return Feql (key1, key2); |
| 3941 | } | 3967 | } |
| @@ -3944,7 +3970,7 @@ cmpfn_eql (Lisp_Object key1, Lisp_Object key2, struct hash_table_test *ht) | |||
| 3944 | Value is true if KEY1 and KEY2 are the same. */ | 3970 | Value is true if KEY1 and KEY2 are the same. */ |
| 3945 | 3971 | ||
| 3946 | static Lisp_Object | 3972 | static Lisp_Object |
| 3947 | cmpfn_equal (Lisp_Object key1, Lisp_Object key2, struct hash_table_test *ht) | 3973 | cmpfn_equal (Lisp_Object key1, Lisp_Object key2, struct Lisp_Hash_Table *h) |
| 3948 | { | 3974 | { |
| 3949 | return Fequal (key1, key2); | 3975 | return Fequal (key1, key2); |
| 3950 | } | 3976 | } |
| @@ -3955,16 +3981,17 @@ cmpfn_equal (Lisp_Object key1, Lisp_Object key2, struct hash_table_test *ht) | |||
| 3955 | 3981 | ||
| 3956 | static Lisp_Object | 3982 | static Lisp_Object |
| 3957 | cmpfn_user_defined (Lisp_Object key1, Lisp_Object key2, | 3983 | cmpfn_user_defined (Lisp_Object key1, Lisp_Object key2, |
| 3958 | struct hash_table_test *ht) | 3984 | struct Lisp_Hash_Table *h) |
| 3959 | { | 3985 | { |
| 3960 | return call2 (ht->user_cmp_function, key1, key2); | 3986 | Lisp_Object args[] = { h->test.user_cmp_function, key1, key2 }; |
| 3987 | return hash_table_user_defined_call (ARRAYELTS (args), args, h); | ||
| 3961 | } | 3988 | } |
| 3962 | 3989 | ||
| 3963 | /* Ignore HT and return a hash code for KEY which uses 'eq' to compare | 3990 | /* Ignore HT and return a hash code for KEY which uses 'eq' to compare |
| 3964 | keys. */ | 3991 | keys. */ |
| 3965 | 3992 | ||
| 3966 | static Lisp_Object | 3993 | static Lisp_Object |
| 3967 | hashfn_eq (Lisp_Object key, struct hash_table_test *ht) | 3994 | hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h) |
| 3968 | { | 3995 | { |
| 3969 | return make_fixnum (XHASH (key) ^ XTYPE (key)); | 3996 | return make_fixnum (XHASH (key) ^ XTYPE (key)); |
| 3970 | } | 3997 | } |
| @@ -3973,7 +4000,7 @@ hashfn_eq (Lisp_Object key, struct hash_table_test *ht) | |||
| 3973 | The hash code is at most INTMASK. */ | 4000 | The hash code is at most INTMASK. */ |
| 3974 | 4001 | ||
| 3975 | Lisp_Object | 4002 | Lisp_Object |
| 3976 | hashfn_equal (Lisp_Object key, struct hash_table_test *ht) | 4003 | hashfn_equal (Lisp_Object key, struct Lisp_Hash_Table *h) |
| 3977 | { | 4004 | { |
| 3978 | return make_fixnum (sxhash (key, 0)); | 4005 | return make_fixnum (sxhash (key, 0)); |
| 3979 | } | 4006 | } |
| @@ -3982,19 +4009,19 @@ hashfn_equal (Lisp_Object key, struct hash_table_test *ht) | |||
| 3982 | The hash code is at most INTMASK. */ | 4009 | The hash code is at most INTMASK. */ |
| 3983 | 4010 | ||
| 3984 | Lisp_Object | 4011 | Lisp_Object |
| 3985 | hashfn_eql (Lisp_Object key, struct hash_table_test *ht) | 4012 | hashfn_eql (Lisp_Object key, struct Lisp_Hash_Table *h) |
| 3986 | { | 4013 | { |
| 3987 | return (FLOATP (key) || BIGNUMP (key) ? hashfn_equal : hashfn_eq) (key, ht); | 4014 | return (FLOATP (key) || BIGNUMP (key) ? hashfn_equal : hashfn_eq) (key, h); |
| 3988 | } | 4015 | } |
| 3989 | 4016 | ||
| 3990 | /* Given HT, return a hash code for KEY which uses a user-defined | 4017 | /* Given HT, return a hash code for KEY which uses a user-defined |
| 3991 | function to compare keys. */ | 4018 | function to compare keys. */ |
| 3992 | 4019 | ||
| 3993 | static Lisp_Object | 4020 | static Lisp_Object |
| 3994 | hashfn_user_defined (Lisp_Object key, struct hash_table_test *ht) | 4021 | hashfn_user_defined (Lisp_Object key, struct Lisp_Hash_Table *h) |
| 3995 | { | 4022 | { |
| 3996 | Lisp_Object hash = call1 (ht->user_hash_function, key); | 4023 | Lisp_Object args[] = { h->test.user_hash_function, key }; |
| 3997 | return hashfn_eq (hash, ht); | 4024 | return hash_table_user_defined_call (ARRAYELTS (args), args, h); |
| 3998 | } | 4025 | } |
| 3999 | 4026 | ||
| 4000 | struct hash_table_test const | 4027 | struct hash_table_test const |
| @@ -4088,6 +4115,7 @@ make_hash_table (struct hash_table_test test, EMACS_INT size, | |||
| 4088 | h->index = make_vector (index_size, make_fixnum (-1)); | 4115 | h->index = make_vector (index_size, make_fixnum (-1)); |
| 4089 | h->next_weak = NULL; | 4116 | h->next_weak = NULL; |
| 4090 | h->purecopy = purecopy; | 4117 | h->purecopy = purecopy; |
| 4118 | h->mutable = true; | ||
| 4091 | 4119 | ||
| 4092 | /* Set up the free list. */ | 4120 | /* Set up the free list. */ |
| 4093 | for (i = 0; i < size - 1; ++i) | 4121 | for (i = 0; i < size - 1; ++i) |
| @@ -4113,6 +4141,7 @@ copy_hash_table (struct Lisp_Hash_Table *h1) | |||
| 4113 | 4141 | ||
| 4114 | h2 = allocate_hash_table (); | 4142 | h2 = allocate_hash_table (); |
| 4115 | *h2 = *h1; | 4143 | *h2 = *h1; |
| 4144 | h2->mutable = true; | ||
| 4116 | h2->key_and_value = Fcopy_sequence (h1->key_and_value); | 4145 | h2->key_and_value = Fcopy_sequence (h1->key_and_value); |
| 4117 | h2->hash = Fcopy_sequence (h1->hash); | 4146 | h2->hash = Fcopy_sequence (h1->hash); |
| 4118 | h2->next = Fcopy_sequence (h1->next); | 4147 | h2->next = Fcopy_sequence (h1->next); |
| @@ -4217,7 +4246,7 @@ hash_table_rehash (struct Lisp_Hash_Table *h) | |||
| 4217 | if (!NILP (HASH_HASH (h, i))) | 4246 | if (!NILP (HASH_HASH (h, i))) |
| 4218 | { | 4247 | { |
| 4219 | Lisp_Object key = HASH_KEY (h, i); | 4248 | Lisp_Object key = HASH_KEY (h, i); |
| 4220 | Lisp_Object hash_code = h->test.hashfn (key, &h->test); | 4249 | Lisp_Object hash_code = h->test.hashfn (key, h); |
| 4221 | set_hash_hash_slot (h, i, hash_code); | 4250 | set_hash_hash_slot (h, i, hash_code); |
| 4222 | } | 4251 | } |
| 4223 | 4252 | ||
| @@ -4255,7 +4284,7 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object *hash) | |||
| 4255 | 4284 | ||
| 4256 | hash_rehash_if_needed (h); | 4285 | hash_rehash_if_needed (h); |
| 4257 | 4286 | ||
| 4258 | Lisp_Object hash_code = h->test.hashfn (key, &h->test); | 4287 | Lisp_Object hash_code = h->test.hashfn (key, h); |
| 4259 | if (hash) | 4288 | if (hash) |
| 4260 | *hash = hash_code; | 4289 | *hash = hash_code; |
| 4261 | 4290 | ||
| @@ -4265,12 +4294,19 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object *hash) | |||
| 4265 | if (EQ (key, HASH_KEY (h, i)) | 4294 | if (EQ (key, HASH_KEY (h, i)) |
| 4266 | || (h->test.cmpfn | 4295 | || (h->test.cmpfn |
| 4267 | && EQ (hash_code, HASH_HASH (h, i)) | 4296 | && EQ (hash_code, HASH_HASH (h, i)) |
| 4268 | && !NILP (h->test.cmpfn (key, HASH_KEY (h, i), &h->test)))) | 4297 | && !NILP (h->test.cmpfn (key, HASH_KEY (h, i), h)))) |
| 4269 | break; | 4298 | break; |
| 4270 | 4299 | ||
| 4271 | return i; | 4300 | return i; |
| 4272 | } | 4301 | } |
| 4273 | 4302 | ||
| 4303 | static void | ||
| 4304 | check_mutable_hash_table (Lisp_Object obj, struct Lisp_Hash_Table *h) | ||
| 4305 | { | ||
| 4306 | if (!h->mutable) | ||
| 4307 | signal_error ("hash table test modifies table", obj); | ||
| 4308 | eassert (!PURE_P (h)); | ||
| 4309 | } | ||
| 4274 | 4310 | ||
| 4275 | /* Put an entry into hash table H that associates KEY with VALUE. | 4311 | /* Put an entry into hash table H that associates KEY with VALUE. |
| 4276 | HASH is a previously computed hash code of KEY. | 4312 | HASH is a previously computed hash code of KEY. |
| @@ -4310,7 +4346,7 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value, | |||
| 4310 | void | 4346 | void |
| 4311 | hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key) | 4347 | hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key) |
| 4312 | { | 4348 | { |
| 4313 | Lisp_Object hash_code = h->test.hashfn (key, &h->test); | 4349 | Lisp_Object hash_code = h->test.hashfn (key, h); |
| 4314 | ptrdiff_t start_of_bucket = XUFIXNUM (hash_code) % ASIZE (h->index); | 4350 | ptrdiff_t start_of_bucket = XUFIXNUM (hash_code) % ASIZE (h->index); |
| 4315 | ptrdiff_t prev = -1; | 4351 | ptrdiff_t prev = -1; |
| 4316 | 4352 | ||
| @@ -4323,7 +4359,7 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key) | |||
| 4323 | if (EQ (key, HASH_KEY (h, i)) | 4359 | if (EQ (key, HASH_KEY (h, i)) |
| 4324 | || (h->test.cmpfn | 4360 | || (h->test.cmpfn |
| 4325 | && EQ (hash_code, HASH_HASH (h, i)) | 4361 | && EQ (hash_code, HASH_HASH (h, i)) |
| 4326 | && !NILP (h->test.cmpfn (key, HASH_KEY (h, i), &h->test)))) | 4362 | && !NILP (h->test.cmpfn (key, HASH_KEY (h, i), h)))) |
| 4327 | { | 4363 | { |
| 4328 | /* Take entry out of collision chain. */ | 4364 | /* Take entry out of collision chain. */ |
| 4329 | if (prev < 0) | 4365 | if (prev < 0) |
| @@ -4912,7 +4948,7 @@ DEFUN ("clrhash", Fclrhash, Sclrhash, 1, 1, 0, | |||
| 4912 | (Lisp_Object table) | 4948 | (Lisp_Object table) |
| 4913 | { | 4949 | { |
| 4914 | struct Lisp_Hash_Table *h = check_hash_table (table); | 4950 | struct Lisp_Hash_Table *h = check_hash_table (table); |
| 4915 | CHECK_IMPURE (table, h); | 4951 | check_mutable_hash_table (table, h); |
| 4916 | hash_clear (h); | 4952 | hash_clear (h); |
| 4917 | /* Be compatible with XEmacs. */ | 4953 | /* Be compatible with XEmacs. */ |
| 4918 | return table; | 4954 | return table; |
| @@ -4937,7 +4973,7 @@ VALUE. In any case, return VALUE. */) | |||
| 4937 | (Lisp_Object key, Lisp_Object value, Lisp_Object table) | 4973 | (Lisp_Object key, Lisp_Object value, Lisp_Object table) |
| 4938 | { | 4974 | { |
| 4939 | struct Lisp_Hash_Table *h = check_hash_table (table); | 4975 | struct Lisp_Hash_Table *h = check_hash_table (table); |
| 4940 | CHECK_IMPURE (table, h); | 4976 | check_mutable_hash_table (table, h); |
| 4941 | 4977 | ||
| 4942 | Lisp_Object hash; | 4978 | Lisp_Object hash; |
| 4943 | ptrdiff_t i = hash_lookup (h, key, &hash); | 4979 | ptrdiff_t i = hash_lookup (h, key, &hash); |
| @@ -4955,7 +4991,7 @@ DEFUN ("remhash", Fremhash, Sremhash, 2, 2, 0, | |||
| 4955 | (Lisp_Object key, Lisp_Object table) | 4991 | (Lisp_Object key, Lisp_Object table) |
| 4956 | { | 4992 | { |
| 4957 | struct Lisp_Hash_Table *h = check_hash_table (table); | 4993 | struct Lisp_Hash_Table *h = check_hash_table (table); |
| 4958 | CHECK_IMPURE (table, h); | 4994 | check_mutable_hash_table (table, h); |
| 4959 | hash_remove_from_table (h, key); | 4995 | hash_remove_from_table (h, key); |
| 4960 | return Qnil; | 4996 | return Qnil; |
| 4961 | } | 4997 | } |
diff --git a/src/lisp.h b/src/lisp.h index e5edb8fd125..6d101fed908 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -2225,6 +2225,8 @@ INLINE int | |||
| 2225 | 2225 | ||
| 2226 | /* The structure of a Lisp hash table. */ | 2226 | /* The structure of a Lisp hash table. */ |
| 2227 | 2227 | ||
| 2228 | struct Lisp_Hash_Table; | ||
| 2229 | |||
| 2228 | struct hash_table_test | 2230 | struct hash_table_test |
| 2229 | { | 2231 | { |
| 2230 | /* Name of the function used to compare keys. */ | 2232 | /* Name of the function used to compare keys. */ |
| @@ -2237,10 +2239,10 @@ struct hash_table_test | |||
| 2237 | Lisp_Object user_cmp_function; | 2239 | Lisp_Object user_cmp_function; |
| 2238 | 2240 | ||
| 2239 | /* C function to compare two keys. */ | 2241 | /* C function to compare two keys. */ |
| 2240 | Lisp_Object (*cmpfn) (Lisp_Object, Lisp_Object, struct hash_table_test *t); | 2242 | Lisp_Object (*cmpfn) (Lisp_Object, Lisp_Object, struct Lisp_Hash_Table *); |
| 2241 | 2243 | ||
| 2242 | /* C function to compute hash code. */ | 2244 | /* C function to compute hash code. */ |
| 2243 | Lisp_Object (*hashfn) (Lisp_Object, struct hash_table_test *t); | 2245 | Lisp_Object (*hashfn) (Lisp_Object, struct Lisp_Hash_Table *); |
| 2244 | }; | 2246 | }; |
| 2245 | 2247 | ||
| 2246 | struct Lisp_Hash_Table | 2248 | struct Lisp_Hash_Table |
| @@ -2289,6 +2291,11 @@ struct Lisp_Hash_Table | |||
| 2289 | changed afterwards. */ | 2291 | changed afterwards. */ |
| 2290 | bool purecopy; | 2292 | bool purecopy; |
| 2291 | 2293 | ||
| 2294 | /* True if the table is mutable. Ordinarily tables are mutable, but | ||
| 2295 | pure tables are not, and while a table is being mutated it is | ||
| 2296 | immutable for recursive attempts to mutate it. */ | ||
| 2297 | bool mutable; | ||
| 2298 | |||
| 2292 | /* Resize hash table when number of entries / table size is >= this | 2299 | /* Resize hash table when number of entries / table size is >= this |
| 2293 | ratio. */ | 2300 | ratio. */ |
| 2294 | float rehash_threshold; | 2301 | float rehash_threshold; |
| @@ -3591,8 +3598,8 @@ extern void hexbuf_digest (char *, void const *, int); | |||
| 3591 | extern char *extract_data_from_object (Lisp_Object, ptrdiff_t *, ptrdiff_t *); | 3598 | extern char *extract_data_from_object (Lisp_Object, ptrdiff_t *, ptrdiff_t *); |
| 3592 | EMACS_UINT hash_string (char const *, ptrdiff_t); | 3599 | EMACS_UINT hash_string (char const *, ptrdiff_t); |
| 3593 | EMACS_UINT sxhash (Lisp_Object, int); | 3600 | EMACS_UINT sxhash (Lisp_Object, int); |
| 3594 | Lisp_Object hashfn_eql (Lisp_Object, struct hash_table_test *); | 3601 | Lisp_Object hashfn_eql (Lisp_Object, struct Lisp_Hash_Table *); |
| 3595 | Lisp_Object hashfn_equal (Lisp_Object, struct hash_table_test *); | 3602 | Lisp_Object hashfn_equal (Lisp_Object, struct Lisp_Hash_Table *); |
| 3596 | Lisp_Object make_hash_table (struct hash_table_test, EMACS_INT, float, float, | 3603 | Lisp_Object make_hash_table (struct hash_table_test, EMACS_INT, float, float, |
| 3597 | Lisp_Object, bool); | 3604 | Lisp_Object, bool); |
| 3598 | ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object *); | 3605 | ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object *); |
diff --git a/src/pdumper.c b/src/pdumper.c index 206a1968909..2abac80a372 100644 --- a/src/pdumper.c +++ b/src/pdumper.c | |||
| @@ -2742,6 +2742,7 @@ dump_hash_table (struct dump_context *ctx, | |||
| 2742 | DUMP_FIELD_COPY (out, hash, count); | 2742 | DUMP_FIELD_COPY (out, hash, count); |
| 2743 | DUMP_FIELD_COPY (out, hash, next_free); | 2743 | DUMP_FIELD_COPY (out, hash, next_free); |
| 2744 | DUMP_FIELD_COPY (out, hash, purecopy); | 2744 | DUMP_FIELD_COPY (out, hash, purecopy); |
| 2745 | DUMP_FIELD_COPY (out, hash, mutable); | ||
| 2745 | DUMP_FIELD_COPY (out, hash, rehash_threshold); | 2746 | DUMP_FIELD_COPY (out, hash, rehash_threshold); |
| 2746 | DUMP_FIELD_COPY (out, hash, rehash_size); | 2747 | DUMP_FIELD_COPY (out, hash, rehash_size); |
| 2747 | dump_field_lv (ctx, out, hash, &hash->key_and_value, WEIGHT_STRONG); | 2748 | dump_field_lv (ctx, out, hash, &hash->key_and_value, WEIGHT_STRONG); |
diff --git a/src/profiler.c b/src/profiler.c index e9b6a37d06b..ed0e9ddd881 100644 --- a/src/profiler.c +++ b/src/profiler.c | |||
| @@ -37,8 +37,8 @@ saturated_add (EMACS_INT a, EMACS_INT b) | |||
| 37 | typedef struct Lisp_Hash_Table log_t; | 37 | typedef struct Lisp_Hash_Table log_t; |
| 38 | 38 | ||
| 39 | static Lisp_Object cmpfn_profiler (Lisp_Object, Lisp_Object, | 39 | static Lisp_Object cmpfn_profiler (Lisp_Object, Lisp_Object, |
| 40 | struct hash_table_test *); | 40 | struct Lisp_Hash_Table *); |
| 41 | static Lisp_Object hashfn_profiler (Lisp_Object, struct hash_table_test *); | 41 | static Lisp_Object hashfn_profiler (Lisp_Object, struct Lisp_Hash_Table *); |
| 42 | 42 | ||
| 43 | static const struct hash_table_test hashtest_profiler = | 43 | static const struct hash_table_test hashtest_profiler = |
| 44 | { | 44 | { |
| @@ -528,7 +528,7 @@ the same lambda expression, or are really unrelated function. */) | |||
| 528 | } | 528 | } |
| 529 | 529 | ||
| 530 | static Lisp_Object | 530 | static Lisp_Object |
| 531 | cmpfn_profiler (Lisp_Object bt1, Lisp_Object bt2, struct hash_table_test *t) | 531 | cmpfn_profiler (Lisp_Object bt1, Lisp_Object bt2, struct Lisp_Hash_Table *h) |
| 532 | { | 532 | { |
| 533 | if (VECTORP (bt1) && VECTORP (bt2)) | 533 | if (VECTORP (bt1) && VECTORP (bt2)) |
| 534 | { | 534 | { |
| @@ -545,7 +545,7 @@ cmpfn_profiler (Lisp_Object bt1, Lisp_Object bt2, struct hash_table_test *t) | |||
| 545 | } | 545 | } |
| 546 | 546 | ||
| 547 | static Lisp_Object | 547 | static Lisp_Object |
| 548 | hashfn_profiler (Lisp_Object bt, struct hash_table_test *ht) | 548 | hashfn_profiler (Lisp_Object bt, struct Lisp_Hash_Table *h) |
| 549 | { | 549 | { |
| 550 | EMACS_UINT hash; | 550 | EMACS_UINT hash; |
| 551 | if (VECTORP (bt)) | 551 | if (VECTORP (bt)) |