aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2019-07-26 14:24:02 -0400
committerStefan Monnier2019-07-26 15:03:03 -0400
commitc74da403aa95ec67598c41aa4f1b97975391135b (patch)
tree6d71f3384c6c5994e12fe771e4ab2601d5d93c8f /src
parentbbff294bf455a9ad4ae66edce8e70f29a40e2e6d (diff)
downloademacs-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.c45
-rw-r--r--src/lisp.h5
2 files changed, 32 insertions, 18 deletions
diff --git a/src/fns.c b/src/fns.c
index 49ec0a85378..3c85dbeae53 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -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