diff options
| author | Stefan Monnier | 2019-07-26 14:24:02 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2019-07-26 15:03:03 -0400 |
| commit | c74da403aa95ec67598c41aa4f1b97975391135b (patch) | |
| tree | 6d71f3384c6c5994e12fe771e4ab2601d5d93c8f /src | |
| parent | bbff294bf455a9ad4ae66edce8e70f29a40e2e6d (diff) | |
| download | emacs-c74da403aa95ec67598c41aa4f1b97975391135b.tar.gz emacs-c74da403aa95ec67598c41aa4f1b97975391135b.zip | |
* src/fns.c: Use `EQ (key, Qunbound)` to check if a slot is in use
(make_hash_table): Use Qunbound for the key_and_value table.
(maybe_resize_hash_table): Set new key_and_value slots to Qunbound.
(hash_table_rehash): Don't bother copying the old table of hashes since
we're recomputing it completely.
(hash_table_rehash): Use hash_rehash_needed_p more.
(hash_put): Add assertion that the slot was indeed considered empty.
(hash_remove_from_table, hash_clear, sweep_weak_table): Set empty
slot's key to Qunbound.
(Fmaphash): Use `EQ (key, Qunbound)` to check if a slot is in use.
* src/lisp.h (struct Lisp_Hash_Table): Update comments.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fns.c | 45 | ||||
| -rw-r--r-- | src/lisp.h | 5 |
2 files changed, 32 insertions, 18 deletions
| @@ -4119,7 +4119,7 @@ make_hash_table (struct hash_table_test test, EMACS_INT size, | |||
| 4119 | h->rehash_threshold = rehash_threshold; | 4119 | h->rehash_threshold = rehash_threshold; |
| 4120 | h->rehash_size = rehash_size; | 4120 | h->rehash_size = rehash_size; |
| 4121 | h->count = 0; | 4121 | h->count = 0; |
| 4122 | h->key_and_value = make_nil_vector (2 * size); | 4122 | h->key_and_value = make_vector (2 * size, Qunbound); |
| 4123 | h->hash = make_nil_vector (size); | 4123 | h->hash = make_nil_vector (size); |
| 4124 | h->next = make_vector (size, make_fixnum (-1)); | 4124 | h->next = make_vector (size, make_fixnum (-1)); |
| 4125 | h->index = make_vector (hash_index_size (h, size), make_fixnum (-1)); | 4125 | h->index = make_vector (hash_index_size (h, size), make_fixnum (-1)); |
| @@ -4199,9 +4199,16 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) | |||
| 4199 | gc_aset (next, i, make_fixnum (i + 1)); | 4199 | gc_aset (next, i, make_fixnum (i + 1)); |
| 4200 | gc_aset (next, next_size - 1, make_fixnum (-1)); | 4200 | gc_aset (next, next_size - 1, make_fixnum (-1)); |
| 4201 | ptrdiff_t index_size = hash_index_size (h, next_size); | 4201 | ptrdiff_t index_size = hash_index_size (h, next_size); |
| 4202 | |||
| 4203 | /* Build the new&larger key_and_value vector, making sure the new | ||
| 4204 | fields are initialized to `unbound`. */ | ||
| 4202 | Lisp_Object key_and_value | 4205 | Lisp_Object key_and_value |
| 4203 | = larger_vector (h->key_and_value, 2 * (next_size - old_size), | 4206 | = larger_vecalloc (h->key_and_value, 2 * (next_size - old_size), |
| 4204 | 2 * next_size); | 4207 | 2 * next_size); |
| 4208 | for (ptrdiff_t i = ASIZE (h->key_and_value); | ||
| 4209 | i < ASIZE (key_and_value); i++) | ||
| 4210 | ASET (key_and_value, i, Qunbound); | ||
| 4211 | |||
| 4205 | Lisp_Object hash = larger_vector (h->hash, next_size - old_size, | 4212 | Lisp_Object hash = larger_vector (h->hash, next_size - old_size, |
| 4206 | next_size); | 4213 | next_size); |
| 4207 | h->index = make_vector (index_size, make_fixnum (-1)); | 4214 | h->index = make_vector (index_size, make_fixnum (-1)); |
| @@ -4241,17 +4248,16 @@ hash_table_rehash (struct Lisp_Hash_Table *h) | |||
| 4241 | (bug#36447). */ | 4248 | (bug#36447). */ |
| 4242 | h->next = Fcopy_sequence (h->next); | 4249 | h->next = Fcopy_sequence (h->next); |
| 4243 | h->index = Fcopy_sequence (h->index); | 4250 | h->index = Fcopy_sequence (h->index); |
| 4244 | h->hash = Fcopy_sequence (h->hash); | 4251 | h->hash = make_nil_vector (size); |
| 4245 | 4252 | ||
| 4246 | /* Recompute the actual hash codes for each entry in the table. | 4253 | /* Recompute the actual hash codes for each entry in the table. |
| 4247 | Order is still invalid. */ | 4254 | Order is still invalid. */ |
| 4248 | for (ptrdiff_t i = 0; i < size; ++i) | 4255 | for (ptrdiff_t i = 0; i < size; ++i) |
| 4249 | if (!NILP (HASH_HASH (h, i))) | 4256 | { |
| 4250 | { | 4257 | Lisp_Object key = HASH_KEY (h, i); |
| 4251 | Lisp_Object key = HASH_KEY (h, i); | 4258 | if (!EQ (key, Qunbound)) |
| 4252 | Lisp_Object hash_code = h->test.hashfn (key, h); | 4259 | set_hash_hash_slot (h, i, h->test.hashfn (key, h)); |
| 4253 | set_hash_hash_slot (h, i, hash_code); | 4260 | } |
| 4254 | } | ||
| 4255 | 4261 | ||
| 4256 | /* Reset the index so that any slot we don't fill below is marked | 4262 | /* Reset the index so that any slot we don't fill below is marked |
| 4257 | invalid. */ | 4263 | invalid. */ |
| @@ -4271,7 +4277,7 @@ hash_table_rehash (struct Lisp_Hash_Table *h) | |||
| 4271 | /* Finally, mark the hash table as having a valid hash order. | 4277 | /* Finally, mark the hash table as having a valid hash order. |
| 4272 | Do this last so that if we're interrupted, we retry on next | 4278 | Do this last so that if we're interrupted, we retry on next |
| 4273 | access. */ | 4279 | access. */ |
| 4274 | eassert (h->count < 0); | 4280 | eassert (hash_rehash_needed_p (h)); |
| 4275 | h->count = -h->count; | 4281 | h->count = -h->count; |
| 4276 | eassert (!hash_rehash_needed_p (h)); | 4282 | eassert (!hash_rehash_needed_p (h)); |
| 4277 | } | 4283 | } |
| @@ -4329,6 +4335,8 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value, | |||
| 4329 | 4335 | ||
| 4330 | /* Store key/value in the key_and_value vector. */ | 4336 | /* Store key/value in the key_and_value vector. */ |
| 4331 | i = h->next_free; | 4337 | i = h->next_free; |
| 4338 | eassert (NILP (HASH_HASH (h, i))); | ||
| 4339 | eassert (EQ (Qunbound, (HASH_KEY (h, i)))); | ||
| 4332 | h->next_free = HASH_NEXT (h, i); | 4340 | h->next_free = HASH_NEXT (h, i); |
| 4333 | set_hash_key_slot (h, i, key); | 4341 | set_hash_key_slot (h, i, key); |
| 4334 | set_hash_value_slot (h, i, value); | 4342 | set_hash_value_slot (h, i, value); |
| @@ -4372,7 +4380,7 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key) | |||
| 4372 | 4380 | ||
| 4373 | /* Clear slots in key_and_value and add the slots to | 4381 | /* Clear slots in key_and_value and add the slots to |
| 4374 | the free list. */ | 4382 | the free list. */ |
| 4375 | set_hash_key_slot (h, i, Qnil); | 4383 | set_hash_key_slot (h, i, Qunbound); |
| 4376 | set_hash_value_slot (h, i, Qnil); | 4384 | set_hash_value_slot (h, i, Qnil); |
| 4377 | set_hash_hash_slot (h, i, Qnil); | 4385 | set_hash_hash_slot (h, i, Qnil); |
| 4378 | set_hash_next_slot (h, i, h->next_free); | 4386 | set_hash_next_slot (h, i, h->next_free); |
| @@ -4399,7 +4407,7 @@ hash_clear (struct Lisp_Hash_Table *h) | |||
| 4399 | for (i = 0; i < size; ++i) | 4407 | for (i = 0; i < size; ++i) |
| 4400 | { | 4408 | { |
| 4401 | set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1); | 4409 | set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1); |
| 4402 | set_hash_key_slot (h, i, Qnil); | 4410 | set_hash_key_slot (h, i, Qunbound); |
| 4403 | set_hash_value_slot (h, i, Qnil); | 4411 | set_hash_value_slot (h, i, Qnil); |
| 4404 | set_hash_hash_slot (h, i, Qnil); | 4412 | set_hash_hash_slot (h, i, Qnil); |
| 4405 | } | 4413 | } |
| @@ -4458,6 +4466,8 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p) | |||
| 4458 | 4466 | ||
| 4459 | if (remove_entries_p) | 4467 | if (remove_entries_p) |
| 4460 | { | 4468 | { |
| 4469 | eassert (!remove_p | ||
| 4470 | == (key_known_to_survive_p && value_known_to_survive_p)); | ||
| 4461 | if (remove_p) | 4471 | if (remove_p) |
| 4462 | { | 4472 | { |
| 4463 | /* Take out of collision chain. */ | 4473 | /* Take out of collision chain. */ |
| @@ -4471,7 +4481,7 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p) | |||
| 4471 | h->next_free = i; | 4481 | h->next_free = i; |
| 4472 | 4482 | ||
| 4473 | /* Clear key, value, and hash. */ | 4483 | /* Clear key, value, and hash. */ |
| 4474 | set_hash_key_slot (h, i, Qnil); | 4484 | set_hash_key_slot (h, i, Qunbound); |
| 4475 | set_hash_value_slot (h, i, Qnil); | 4485 | set_hash_value_slot (h, i, Qnil); |
| 4476 | set_hash_hash_slot (h, i, Qnil); | 4486 | set_hash_hash_slot (h, i, Qnil); |
| 4477 | 4487 | ||
| @@ -5009,8 +5019,11 @@ FUNCTION is called with two arguments, KEY and VALUE. | |||
| 5009 | struct Lisp_Hash_Table *h = check_hash_table (table); | 5019 | struct Lisp_Hash_Table *h = check_hash_table (table); |
| 5010 | 5020 | ||
| 5011 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) | 5021 | for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) |
| 5012 | if (!NILP (HASH_HASH (h, i))) | 5022 | { |
| 5013 | call2 (function, HASH_KEY (h, i), HASH_VALUE (h, i)); | 5023 | Lisp_Object k = HASH_KEY (h, i); |
| 5024 | if (!EQ (k, Qunbound)) | ||
| 5025 | call2 (function, k, HASH_VALUE (h, i)); | ||
| 5026 | } | ||
| 5014 | 5027 | ||
| 5015 | return Qnil; | 5028 | return Qnil; |
| 5016 | } | 5029 | } |
diff --git a/src/lisp.h b/src/lisp.h index 17495777378..680798621ca 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -2274,8 +2274,8 @@ struct Lisp_Hash_Table | |||
| 2274 | weakness of the table. */ | 2274 | weakness of the table. */ |
| 2275 | Lisp_Object weak; | 2275 | Lisp_Object weak; |
| 2276 | 2276 | ||
| 2277 | /* Vector of hash codes. If hash[I] is nil, this means that the | 2277 | /* Vector of hash codes. |
| 2278 | I-th entry is unused. */ | 2278 | If the I-th entry is unused, then hash[I] should be nil. */ |
| 2279 | Lisp_Object hash; | 2279 | Lisp_Object hash; |
| 2280 | 2280 | ||
| 2281 | /* Vector used to chain entries. If entry I is free, next[I] is the | 2281 | /* Vector used to chain entries. If entry I is free, next[I] is the |
| @@ -2323,6 +2323,7 @@ struct Lisp_Hash_Table | |||
| 2323 | 2323 | ||
| 2324 | /* Vector of keys and values. The key of item I is found at index | 2324 | /* Vector of keys and values. The key of item I is found at index |
| 2325 | 2 * I, the value is found at index 2 * I + 1. | 2325 | 2 * I, the value is found at index 2 * I + 1. |
| 2326 | If the key is equal to Qunbound, then this slot is unused. | ||
| 2326 | This is gc_marked specially if the table is weak. */ | 2327 | This is gc_marked specially if the table is weak. */ |
| 2327 | Lisp_Object key_and_value; | 2328 | Lisp_Object key_and_value; |
| 2328 | 2329 | ||