From 0dc5a85a1c3772a6e78f077719d82f437f626b1e Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 26 Jul 2019 14:59:15 -0400 Subject: [PATCH] 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. --- src/fns.c | 15 ++++++++------- src/lisp.h | 2 +- src/pdumper.c | 10 ++++++++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/fns.c b/src/fns.c index 3c85dbeae53..acc6d46db85 100644 --- a/src/fns.c +++ b/src/fns.c @@ -4246,9 +4246,9 @@ hash_table_rehash (struct Lisp_Hash_Table *h) /* These structures may have been purecopied and shared (bug#36447). */ + Lisp_Object hash = make_nil_vector (size); h->next = Fcopy_sequence (h->next); h->index = Fcopy_sequence (h->index); - h->hash = make_nil_vector (size); /* Recompute the actual hash codes for each entry in the table. Order is still invalid. */ @@ -4256,7 +4256,7 @@ hash_table_rehash (struct Lisp_Hash_Table *h) { Lisp_Object key = HASH_KEY (h, i); if (!EQ (key, Qunbound)) - set_hash_hash_slot (h, i, h->test.hashfn (key, h)); + ASET (hash, i, h->test.hashfn (key, h)); } /* 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) /* Rebuild the collision chains. */ for (ptrdiff_t i = 0; i < size; ++i) - if (!NILP (HASH_HASH (h, i))) + if (!NILP (AREF (hash, i))) { - EMACS_UINT hash_code = XUFIXNUM (HASH_HASH (h, i)); + EMACS_UINT hash_code = XUFIXNUM (AREF (hash, i)); ptrdiff_t start_of_bucket = hash_code % ASIZE (h->index); set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket)); set_hash_index_slot (h, start_of_bucket, i); @@ -4278,7 +4278,7 @@ hash_table_rehash (struct Lisp_Hash_Table *h) Do this last so that if we're interrupted, we retry on next access. */ eassert (hash_rehash_needed_p (h)); - h->count = -h->count; + h->hash = hash; eassert (!hash_rehash_needed_p (h)); } @@ -4483,7 +4483,8 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p) /* Clear key, value, and hash. */ set_hash_key_slot (h, i, Qunbound); set_hash_value_slot (h, i, Qnil); - set_hash_hash_slot (h, i, Qnil); + if (!NILP (h->hash)) + set_hash_hash_slot (h, i, Qnil); eassert (h->count != 0); h->count += h->count > 0 ? -1 : 1; @@ -4889,7 +4890,7 @@ DEFUN ("hash-table-count", Fhash_table_count, Shash_table_count, 1, 1, 0, (Lisp_Object table) { struct Lisp_Hash_Table *h = check_hash_table (table); - hash_rehash_if_needed (h); + eassert (h->count >= 0); return make_fixnum (h->count); } 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); INLINE bool hash_rehash_needed_p (const struct Lisp_Hash_Table *h) { - return h->count < 0; + return NILP (h->hash); } 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) hash_rehash_if_needed (XHASH_TABLE (table_orig)); Lisp_Object table_rehashed = Fcopy_hash_table (table_orig); eassert (!hash_rehash_needed_p (XHASH_TABLE (table_rehashed))); - XHASH_TABLE (table_rehashed)->count *= -1; + XHASH_TABLE (table_rehashed)->hash = Qnil; eassert (count == 0 || hash_rehash_needed_p (XHASH_TABLE (table_rehashed))); hash_rehash_if_needed (XHASH_TABLE (table_rehashed)); eassert (!hash_rehash_needed_p (XHASH_TABLE (table_rehashed))); @@ -2733,7 +2733,13 @@ dump_hash_table (struct dump_context *ctx, the need to rehash-on-access if we can load the dump where we want. */ if (hash->count > 0 && !is_stable) - hash->count = -hash->count; + /* Hash codes will have to be recomputed anyway, so let's not dump them. + Also set `hash` to nil for hash_rehash_needed_p. + We could also refrain from dumping the `next' and `index' vectors, + except that `next' is currently used for HASH_TABLE_SIZE and + we'd have to rebuild the next_free list as well as adjust + sweep_weak_hash_table for the case where there's no `index'. */ + hash->hash = Qnil; START_DUMP_PVEC (ctx, &hash->header, struct Lisp_Hash_Table, out); dump_pseudovector_lisp_fields (ctx, &out->header, &hash->header); -- 2.39.2