diff options
| author | Stefan Monnier | 2019-07-26 14:59:15 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2019-07-26 15:03:03 -0400 |
| commit | 0dc5a85a1c3772a6e78f077719d82f437f626b1e (patch) | |
| tree | abe77c1082f55453027d08937302a3e122069be7 /src | |
| parent | c74da403aa95ec67598c41aa4f1b97975391135b (diff) | |
| download | emacs-0dc5a85a1c3772a6e78f077719d82f437f626b1e.tar.gz emacs-0dc5a85a1c3772a6e78f077719d82f437f626b1e.zip | |
Don't dump the `hash` vector if it will need to be recomputed anyway
* src/fns.c (hash_table_rehash): Only set `hash` field at the end.
(sweep_weak_table): Only set slot of `hash` vector when that vector exists.
(Fhash_table_count): No need to hash_rehash_if_needed any more.
* src/lisp.h (hash_rehash_needed_p): Test the presence of `hash` instead.
* src/pdumper.c (check_hash_table_rehash, dump_hash_table):
Set `hash` to nil to indicate that the table needs to be rehashed.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fns.c | 15 | ||||
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/pdumper.c | 10 |
3 files changed, 17 insertions, 10 deletions
| @@ -4246,9 +4246,9 @@ hash_table_rehash (struct Lisp_Hash_Table *h) | |||
| 4246 | 4246 | ||
| 4247 | /* These structures may have been purecopied and shared | 4247 | /* These structures may have been purecopied and shared |
| 4248 | (bug#36447). */ | 4248 | (bug#36447). */ |
| 4249 | Lisp_Object hash = make_nil_vector (size); | ||
| 4249 | h->next = Fcopy_sequence (h->next); | 4250 | h->next = Fcopy_sequence (h->next); |
| 4250 | h->index = Fcopy_sequence (h->index); | 4251 | h->index = Fcopy_sequence (h->index); |
| 4251 | h->hash = make_nil_vector (size); | ||
| 4252 | 4252 | ||
| 4253 | /* Recompute the actual hash codes for each entry in the table. | 4253 | /* Recompute the actual hash codes for each entry in the table. |
| 4254 | Order is still invalid. */ | 4254 | Order is still invalid. */ |
| @@ -4256,7 +4256,7 @@ hash_table_rehash (struct Lisp_Hash_Table *h) | |||
| 4256 | { | 4256 | { |
| 4257 | Lisp_Object key = HASH_KEY (h, i); | 4257 | Lisp_Object key = HASH_KEY (h, i); |
| 4258 | if (!EQ (key, Qunbound)) | 4258 | if (!EQ (key, Qunbound)) |
| 4259 | set_hash_hash_slot (h, i, h->test.hashfn (key, h)); | 4259 | ASET (hash, i, h->test.hashfn (key, h)); |
| 4260 | } | 4260 | } |
| 4261 | 4261 | ||
| 4262 | /* 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 |
| @@ -4265,9 +4265,9 @@ hash_table_rehash (struct Lisp_Hash_Table *h) | |||
| 4265 | 4265 | ||
| 4266 | /* Rebuild the collision chains. */ | 4266 | /* Rebuild the collision chains. */ |
| 4267 | for (ptrdiff_t i = 0; i < size; ++i) | 4267 | for (ptrdiff_t i = 0; i < size; ++i) |
| 4268 | if (!NILP (HASH_HASH (h, i))) | 4268 | if (!NILP (AREF (hash, i))) |
| 4269 | { | 4269 | { |
| 4270 | EMACS_UINT hash_code = XUFIXNUM (HASH_HASH (h, i)); | 4270 | EMACS_UINT hash_code = XUFIXNUM (AREF (hash, i)); |
| 4271 | ptrdiff_t start_of_bucket = hash_code % ASIZE (h->index); | 4271 | ptrdiff_t start_of_bucket = hash_code % ASIZE (h->index); |
| 4272 | set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket)); | 4272 | set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket)); |
| 4273 | set_hash_index_slot (h, start_of_bucket, i); | 4273 | set_hash_index_slot (h, start_of_bucket, i); |
| @@ -4278,7 +4278,7 @@ hash_table_rehash (struct Lisp_Hash_Table *h) | |||
| 4278 | 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 |
| 4279 | access. */ | 4279 | access. */ |
| 4280 | eassert (hash_rehash_needed_p (h)); | 4280 | eassert (hash_rehash_needed_p (h)); |
| 4281 | h->count = -h->count; | 4281 | h->hash = hash; |
| 4282 | eassert (!hash_rehash_needed_p (h)); | 4282 | eassert (!hash_rehash_needed_p (h)); |
| 4283 | } | 4283 | } |
| 4284 | 4284 | ||
| @@ -4483,7 +4483,8 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p) | |||
| 4483 | /* Clear key, value, and hash. */ | 4483 | /* Clear key, value, and hash. */ |
| 4484 | set_hash_key_slot (h, i, Qunbound); | 4484 | set_hash_key_slot (h, i, Qunbound); |
| 4485 | set_hash_value_slot (h, i, Qnil); | 4485 | set_hash_value_slot (h, i, Qnil); |
| 4486 | set_hash_hash_slot (h, i, Qnil); | 4486 | if (!NILP (h->hash)) |
| 4487 | set_hash_hash_slot (h, i, Qnil); | ||
| 4487 | 4488 | ||
| 4488 | eassert (h->count != 0); | 4489 | eassert (h->count != 0); |
| 4489 | h->count += h->count > 0 ? -1 : 1; | 4490 | h->count += h->count > 0 ? -1 : 1; |
| @@ -4889,7 +4890,7 @@ DEFUN ("hash-table-count", Fhash_table_count, Shash_table_count, 1, 1, 0, | |||
| 4889 | (Lisp_Object table) | 4890 | (Lisp_Object table) |
| 4890 | { | 4891 | { |
| 4891 | struct Lisp_Hash_Table *h = check_hash_table (table); | 4892 | struct Lisp_Hash_Table *h = check_hash_table (table); |
| 4892 | hash_rehash_if_needed (h); | 4893 | eassert (h->count >= 0); |
| 4893 | return make_fixnum (h->count); | 4894 | return make_fixnum (h->count); |
| 4894 | } | 4895 | } |
| 4895 | 4896 | ||
diff --git a/src/lisp.h b/src/lisp.h index 680798621ca..f437609fe1f 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -2388,7 +2388,7 @@ void hash_table_rehash (struct Lisp_Hash_Table *h); | |||
| 2388 | INLINE bool | 2388 | INLINE bool |
| 2389 | hash_rehash_needed_p (const struct Lisp_Hash_Table *h) | 2389 | hash_rehash_needed_p (const struct Lisp_Hash_Table *h) |
| 2390 | { | 2390 | { |
| 2391 | return h->count < 0; | 2391 | return NILP (h->hash); |
| 2392 | } | 2392 | } |
| 2393 | 2393 | ||
| 2394 | INLINE void | 2394 | INLINE void |
diff --git a/src/pdumper.c b/src/pdumper.c index 4ba819b4103..1a5d1f32ba5 100644 --- a/src/pdumper.c +++ b/src/pdumper.c | |||
| @@ -2666,7 +2666,7 @@ check_hash_table_rehash (Lisp_Object table_orig) | |||
| 2666 | hash_rehash_if_needed (XHASH_TABLE (table_orig)); | 2666 | hash_rehash_if_needed (XHASH_TABLE (table_orig)); |
| 2667 | Lisp_Object table_rehashed = Fcopy_hash_table (table_orig); | 2667 | Lisp_Object table_rehashed = Fcopy_hash_table (table_orig); |
| 2668 | eassert (!hash_rehash_needed_p (XHASH_TABLE (table_rehashed))); | 2668 | eassert (!hash_rehash_needed_p (XHASH_TABLE (table_rehashed))); |
| 2669 | XHASH_TABLE (table_rehashed)->count *= -1; | 2669 | XHASH_TABLE (table_rehashed)->hash = Qnil; |
| 2670 | eassert (count == 0 || hash_rehash_needed_p (XHASH_TABLE (table_rehashed))); | 2670 | eassert (count == 0 || hash_rehash_needed_p (XHASH_TABLE (table_rehashed))); |
| 2671 | hash_rehash_if_needed (XHASH_TABLE (table_rehashed)); | 2671 | hash_rehash_if_needed (XHASH_TABLE (table_rehashed)); |
| 2672 | eassert (!hash_rehash_needed_p (XHASH_TABLE (table_rehashed))); | 2672 | eassert (!hash_rehash_needed_p (XHASH_TABLE (table_rehashed))); |
| @@ -2733,7 +2733,13 @@ dump_hash_table (struct dump_context *ctx, | |||
| 2733 | the need to rehash-on-access if we can load the dump where we | 2733 | the need to rehash-on-access if we can load the dump where we |
| 2734 | want. */ | 2734 | want. */ |
| 2735 | if (hash->count > 0 && !is_stable) | 2735 | if (hash->count > 0 && !is_stable) |
| 2736 | hash->count = -hash->count; | 2736 | /* Hash codes will have to be recomputed anyway, so let's not dump them. |
| 2737 | Also set `hash` to nil for hash_rehash_needed_p. | ||
| 2738 | We could also refrain from dumping the `next' and `index' vectors, | ||
| 2739 | except that `next' is currently used for HASH_TABLE_SIZE and | ||
| 2740 | we'd have to rebuild the next_free list as well as adjust | ||
| 2741 | sweep_weak_hash_table for the case where there's no `index'. */ | ||
| 2742 | hash->hash = Qnil; | ||
| 2737 | 2743 | ||
| 2738 | START_DUMP_PVEC (ctx, &hash->header, struct Lisp_Hash_Table, out); | 2744 | START_DUMP_PVEC (ctx, &hash->header, struct Lisp_Hash_Table, out); |
| 2739 | dump_pseudovector_lisp_fields (ctx, &out->header, &hash->header); | 2745 | dump_pseudovector_lisp_fields (ctx, &out->header, &hash->header); |