aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2019-08-21 18:54:08 -0700
committerPaul Eggert2019-08-21 19:01:49 -0700
commitceebf3efbea7faffc01558d88c91250539c737e0 (patch)
tree3f8d585e220804bd18b493f696691ed7e91fad9f /src
parentc64c0230d65260f44f367bac72bfdee50c52a90d (diff)
downloademacs-ceebf3efbea7faffc01558d88c91250539c737e0.tar.gz
emacs-ceebf3efbea7faffc01558d88c91250539c737e0.zip
Fix clrhash bug when hash table needs rehashing
Problem reported by Pip Cet in: https://lists.gnu.org/r/emacs-devel/2019-08/msg00316.html * src/fns.c (maybe_resize_hash_table): Prefer ASET to gc_aset where either will do. Simplify appending of Qunbound values. Put index_size calculation closer to where it’s needed. (hash_clear): If hash_rehash_needed_p (h), don’t clear the nonexistent hash vector. Use memclear to speed up clearing. * src/lisp.h (HASH_TABLE_SIZE): Check that the size is positive, and tell that to the compiler.
Diffstat (limited to 'src')
-rw-r--r--src/fns.c28
-rw-r--r--src/lisp.h9
2 files changed, 17 insertions, 20 deletions
diff --git a/src/fns.c b/src/fns.c
index b606d6299ca..8ca0953fe85 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -4198,21 +4198,20 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
4198 new_size); 4198 new_size);
4199 ptrdiff_t next_size = ASIZE (next); 4199 ptrdiff_t next_size = ASIZE (next);
4200 for (ptrdiff_t i = old_size; i < next_size - 1; i++) 4200 for (ptrdiff_t i = old_size; i < next_size - 1; i++)
4201 gc_aset (next, i, make_fixnum (i + 1)); 4201 ASET (next, i, make_fixnum (i + 1));
4202 gc_aset (next, next_size - 1, make_fixnum (-1)); 4202 ASET (next, next_size - 1, make_fixnum (-1));
4203 ptrdiff_t index_size = hash_index_size (h, next_size);
4204 4203
4205 /* Build the new&larger key_and_value vector, making sure the new 4204 /* Build the new&larger key_and_value vector, making sure the new
4206 fields are initialized to `unbound`. */ 4205 fields are initialized to `unbound`. */
4207 Lisp_Object key_and_value 4206 Lisp_Object key_and_value
4208 = larger_vecalloc (h->key_and_value, 2 * (next_size - old_size), 4207 = larger_vecalloc (h->key_and_value, 2 * (next_size - old_size),
4209 2 * next_size); 4208 2 * next_size);
4210 for (ptrdiff_t i = ASIZE (h->key_and_value); 4209 for (ptrdiff_t i = 2 * old_size; i < 2 * next_size; i++)
4211 i < ASIZE (key_and_value); i++)
4212 ASET (key_and_value, i, Qunbound); 4210 ASET (key_and_value, i, Qunbound);
4213 4211
4214 Lisp_Object hash = larger_vector (h->hash, next_size - old_size, 4212 Lisp_Object hash = larger_vector (h->hash, next_size - old_size,
4215 next_size); 4213 next_size);
4214 ptrdiff_t index_size = hash_index_size (h, next_size);
4216 h->index = make_vector (index_size, make_fixnum (-1)); 4215 h->index = make_vector (index_size, make_fixnum (-1));
4217 h->key_and_value = key_and_value; 4216 h->key_and_value = key_and_value;
4218 h->hash = hash; 4217 h->hash = hash;
@@ -4404,17 +4403,14 @@ hash_clear (struct Lisp_Hash_Table *h)
4404{ 4403{
4405 if (h->count > 0) 4404 if (h->count > 0)
4406 { 4405 {
4407 ptrdiff_t i, size = HASH_TABLE_SIZE (h); 4406 ptrdiff_t size = HASH_TABLE_SIZE (h);
4408 4407 if (!hash_rehash_needed_p (h))
4409 for (i = 0; i < size; ++i) 4408 memclear (XVECTOR (h->hash)->contents, size * word_size);
4410 { 4409 memclear (XVECTOR (h->key_and_value)->contents, size * 2 * word_size);
4411 set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1); 4410 for (ptrdiff_t i = 0; i < size; i++)
4412 set_hash_key_slot (h, i, Qunbound); 4411 set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1);
4413 set_hash_value_slot (h, i, Qnil); 4412
4414 set_hash_hash_slot (h, i, Qnil); 4413 for (ptrdiff_t i = 0; i < ASIZE (h->index); i++)
4415 }
4416
4417 for (i = 0; i < ASIZE (h->index); ++i)
4418 ASET (h->index, i, make_fixnum (-1)); 4414 ASET (h->index, i, make_fixnum (-1));
4419 4415
4420 h->next_free = 0; 4416 h->next_free = 0;
diff --git a/src/lisp.h b/src/lisp.h
index 56ad99b8e39..ae5a81e7b5e 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2307,7 +2307,7 @@ struct Lisp_Hash_Table
2307 weakness of the table. */ 2307 weakness of the table. */
2308 Lisp_Object weak; 2308 Lisp_Object weak;
2309 2309
2310 /* Vector of hash codes. 2310 /* Vector of hash codes, or nil if the table needs rehashing.
2311 If the I-th entry is unused, then hash[I] should be nil. */ 2311 If the I-th entry is unused, then hash[I] should be nil. */
2312 Lisp_Object hash; 2312 Lisp_Object hash;
2313 2313
@@ -2327,8 +2327,7 @@ struct Lisp_Hash_Table
2327 'index' are special and are either ignored by the GC or traced in 2327 'index' are special and are either ignored by the GC or traced in
2328 a special way (e.g. because of weakness). */ 2328 a special way (e.g. because of weakness). */
2329 2329
2330 /* Number of key/value entries in the table. This number is 2330 /* Number of key/value entries in the table. */
2331 negated if the table needs rehashing. */
2332 ptrdiff_t count; 2331 ptrdiff_t count;
2333 2332
2334 /* Index of first free entry in free list, or -1 if none. */ 2333 /* Index of first free entry in free list, or -1 if none. */
@@ -2413,7 +2412,9 @@ HASH_HASH (const struct Lisp_Hash_Table *h, ptrdiff_t idx)
2413INLINE ptrdiff_t 2412INLINE ptrdiff_t
2414HASH_TABLE_SIZE (const struct Lisp_Hash_Table *h) 2413HASH_TABLE_SIZE (const struct Lisp_Hash_Table *h)
2415{ 2414{
2416 return ASIZE (h->next); 2415 ptrdiff_t size = ASIZE (h->next);
2416 eassume (0 < size);
2417 return size;
2417} 2418}
2418 2419
2419void hash_table_rehash (struct Lisp_Hash_Table *h); 2420void hash_table_rehash (struct Lisp_Hash_Table *h);