diff options
| author | Paul Eggert | 2019-07-20 23:21:14 -0700 |
|---|---|---|
| committer | Paul Eggert | 2019-07-20 23:21:41 -0700 |
| commit | 49e80e765b693736a8bb97ae5bfa341d25bf4f02 (patch) | |
| tree | 500758c693dc3b53b8fad751157af270414025a8 /src | |
| parent | 515afc9c15870cd7bd6b96e2d8b89938116923ac (diff) | |
| download | emacs-49e80e765b693736a8bb97ae5bfa341d25bf4f02.tar.gz emacs-49e80e765b693736a8bb97ae5bfa341d25bf4f02.zip | |
Tweak recent hash-table fix
* src/fns.c (maybe_resize_hash_table): Completely initialize the
new ‘next’ vector before allocating more vectors, as this
preserves locality a bit better and it’s safer not to leave an
uninitialized Lisp object around. Use next_size instead of
new_size to compute new index size.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fns.c | 27 |
1 files changed, 12 insertions, 15 deletions
| @@ -4176,19 +4176,23 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) | |||
| 4176 | } | 4176 | } |
| 4177 | if (new_size <= old_size) | 4177 | if (new_size <= old_size) |
| 4178 | new_size = old_size + 1; | 4178 | new_size = old_size + 1; |
| 4179 | double threshold = h->rehash_threshold; | ||
| 4180 | double index_float = new_size / threshold; | ||
| 4181 | EMACS_INT index_size = (index_float < INDEX_SIZE_BOUND + 1 | ||
| 4182 | ? next_almost_prime (index_float) | ||
| 4183 | : INDEX_SIZE_BOUND + 1); | ||
| 4184 | if (INDEX_SIZE_BOUND < max (index_size, 2 * new_size)) | ||
| 4185 | error ("Hash table too large to resize"); | ||
| 4186 | 4179 | ||
| 4187 | /* Allocate all the new vectors before updating *H, to | 4180 | /* Allocate all the new vectors before updating *H, to |
| 4188 | avoid problems if memory is exhausted. larger_vecalloc | 4181 | avoid problems if memory is exhausted. larger_vecalloc |
| 4189 | finishes computing the size of the replacement vectors. */ | 4182 | finishes computing the size of the replacement vectors. */ |
| 4190 | Lisp_Object next = larger_vecalloc (h->next, new_size - old_size, -1); | 4183 | Lisp_Object next = larger_vecalloc (h->next, new_size - old_size, |
| 4184 | INDEX_SIZE_BOUND / 2); | ||
| 4191 | ptrdiff_t next_size = ASIZE (next); | 4185 | ptrdiff_t next_size = ASIZE (next); |
| 4186 | for (ptrdiff_t i = old_size; i < next_size - 1; i++) | ||
| 4187 | gc_aset (next, i, make_fixnum (i + 1)); | ||
| 4188 | gc_aset (next, next_size - 1, make_fixnum (-1)); | ||
| 4189 | double threshold = h->rehash_threshold; | ||
| 4190 | double index_float = next_size / threshold; | ||
| 4191 | EMACS_INT index_size = (index_float < INDEX_SIZE_BOUND + 1 | ||
| 4192 | ? next_almost_prime (index_float) | ||
| 4193 | : INDEX_SIZE_BOUND + 1); | ||
| 4194 | if (INDEX_SIZE_BOUND < index_size) | ||
| 4195 | error ("Hash table too large to resize"); | ||
| 4192 | Lisp_Object key_and_value | 4196 | Lisp_Object key_and_value |
| 4193 | = larger_vector (h->key_and_value, 2 * (next_size - old_size), | 4197 | = larger_vector (h->key_and_value, 2 * (next_size - old_size), |
| 4194 | 2 * next_size); | 4198 | 2 * next_size); |
| @@ -4198,13 +4202,6 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) | |||
| 4198 | h->key_and_value = key_and_value; | 4202 | h->key_and_value = key_and_value; |
| 4199 | h->hash = hash; | 4203 | h->hash = hash; |
| 4200 | h->next = next; | 4204 | h->next = next; |
| 4201 | |||
| 4202 | /* Update the free list. Do it so that new entries are added at | ||
| 4203 | the end of the free list. This makes some operations like | ||
| 4204 | maphash faster. */ | ||
| 4205 | for (ptrdiff_t i = old_size; i < next_size - 1; i++) | ||
| 4206 | set_hash_next_slot (h, i, i + 1); | ||
| 4207 | set_hash_next_slot (h, next_size - 1, -1); | ||
| 4208 | h->next_free = old_size; | 4205 | h->next_free = old_size; |
| 4209 | 4206 | ||
| 4210 | /* Rehash. */ | 4207 | /* Rehash. */ |