aboutsummaryrefslogtreecommitdiffstats
path: root/src/pdumper.c
diff options
context:
space:
mode:
authorMattias EngdegÄrd2023-11-04 16:34:09 +0100
committerMattias EngdegÄrd2024-01-13 20:50:37 +0100
commitd3cefd3e98354929d96c9396e5920e8a123784dc (patch)
treeb0fd45c15faa88216653413229e759444810585d /src/pdumper.c
parentc3d0cc50faf588479db62e20ceabe044dd89e244 (diff)
downloademacs-d3cefd3e98354929d96c9396e5920e8a123784dc.tar.gz
emacs-d3cefd3e98354929d96c9396e5920e8a123784dc.zip
Leaner hash table dumping and thawing
Only dump the actual data, and the test encoded as an enum. This simplifies dumping, makes dump files smaller and saves space at run time. * src/lisp.h (hash_table_std_test_t): New enum. (struct Lisp_Hash_Table): Add frozen_test member, consuming no extra space. * src/fns.c (hashfn_user_defined): Now static. (hash_table_test_from_std): New. (hash_table_rehash): Rename to... (hash_table_thaw): ...this and rewrite. * src/pdumper.c (hash_table_contents): Only include actual data, not unused space. (hash_table_std_test): New. (hash_table_freeze): Set frozen_test from test. (dump_hash_table): Dump frozen_test, not the whole test struct. Don't bother other dumping fields that can be derived.
Diffstat (limited to 'src/pdumper.c')
-rw-r--r--src/pdumper.c63
1 files changed, 27 insertions, 36 deletions
diff --git a/src/pdumper.c b/src/pdumper.c
index 8072148c542..e4349f0cb17 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2646,34 +2646,26 @@ dump_vectorlike_generic (struct dump_context *ctx,
2646 return offset; 2646 return offset;
2647} 2647}
2648 2648
2649/* Return a vector of KEY, VALUE pairs in the given hash table H. The 2649/* Return a vector of KEY, VALUE pairs in the given hash table H.
2650 first H->count pairs are valid, and the rest are unbound. */ 2650 No room for growth is included. */
2651static Lisp_Object 2651static Lisp_Object
2652hash_table_contents (struct Lisp_Hash_Table *h) 2652hash_table_contents (struct Lisp_Hash_Table *h)
2653{ 2653{
2654 if (h->test.hashfn == hashfn_user_defined) 2654 ptrdiff_t old_size = HASH_TABLE_SIZE (h);
2655 error ("cannot dump hash tables with user-defined tests"); /* Bug#36769 */ 2655 ptrdiff_t size = h->count;
2656
2657 ptrdiff_t size = HASH_TABLE_SIZE (h);
2658 Lisp_Object key_and_value = make_uninit_vector (2 * size); 2656 Lisp_Object key_and_value = make_uninit_vector (2 * size);
2659 ptrdiff_t n = 0; 2657 ptrdiff_t n = 0;
2660 2658
2661 /* Make sure key_and_value ends up in the same order; charset.c 2659 /* Make sure key_and_value ends up in the same order; charset.c
2662 relies on it by expecting hash table indices to stay constant 2660 relies on it by expecting hash table indices to stay constant
2663 across the dump. */ 2661 across the dump. */
2664 for (ptrdiff_t i = 0; i < size; i++) 2662 for (ptrdiff_t i = 0; i < old_size; i++)
2665 if (!NILP (HASH_HASH (h, i))) 2663 if (!NILP (HASH_HASH (h, i)))
2666 { 2664 {
2667 ASET (key_and_value, n++, HASH_KEY (h, i)); 2665 ASET (key_and_value, n++, HASH_KEY (h, i));
2668 ASET (key_and_value, n++, HASH_VALUE (h, i)); 2666 ASET (key_and_value, n++, HASH_VALUE (h, i));
2669 } 2667 }
2670 2668
2671 while (n < 2 * size)
2672 {
2673 ASET (key_and_value, n++, Qunbound);
2674 ASET (key_and_value, n++, Qnil);
2675 }
2676
2677 return key_and_value; 2669 return key_and_value;
2678} 2670}
2679 2671
@@ -2686,25 +2678,32 @@ dump_hash_table_list (struct dump_context *ctx)
2686 return 0; 2678 return 0;
2687} 2679}
2688 2680
2689static void 2681static hash_table_std_test_t
2690hash_table_freeze (struct Lisp_Hash_Table *h) 2682hash_table_std_test (const struct hash_table_test *t)
2691{ 2683{
2692 ptrdiff_t npairs = ASIZE (h->key_and_value) / 2; 2684 if (BASE_EQ (t->name, Qeq))
2693 h->key_and_value = hash_table_contents (h); 2685 return Test_eq;
2694 h->next = h->hash = make_fixnum (npairs); 2686 if (BASE_EQ (t->name, Qeql))
2695 h->index = make_fixnum (ASIZE (h->index)); 2687 return Test_eql;
2696 h->next_free = (npairs == h->count ? -1 : h->count); 2688 if (BASE_EQ (t->name, Qequal))
2689 return Test_equal;
2690 error ("cannot dump hash tables with user-defined tests"); /* Bug#36769 */
2697} 2691}
2698 2692
2693/* Compact contents and discard inessential information from a hash table,
2694 preparing it for dumping.
2695 See `hash_table_thaw' for the code that restores the object to a usable
2696 state. */
2699static void 2697static void
2700hash_table_thaw (Lisp_Object hash) 2698hash_table_freeze (struct Lisp_Hash_Table *h)
2701{ 2699{
2702 struct Lisp_Hash_Table *h = XHASH_TABLE (hash); 2700 h->key_and_value = hash_table_contents (h);
2703 h->hash = make_nil_vector (XFIXNUM (h->hash)); 2701 eassert (ASIZE (h->key_and_value) == h->count * 2);
2704 h->next = Fmake_vector (h->next, make_fixnum (-1)); 2702 h->next = Qnil;
2705 h->index = Fmake_vector (h->index, make_fixnum (-1)); 2703 h->hash = Qnil;
2706 2704 h->index = Qnil;
2707 hash_table_rehash (hash); 2705 h->count = 0;
2706 h->frozen_test = hash_table_std_test (&h->test);
2708} 2707}
2709 2708
2710static dump_off 2709static dump_off
@@ -2724,19 +2723,11 @@ dump_hash_table (struct dump_context *ctx, Lisp_Object object)
2724 dump_pseudovector_lisp_fields (ctx, &out->header, &hash->header); 2723 dump_pseudovector_lisp_fields (ctx, &out->header, &hash->header);
2725 /* TODO: dump the hash bucket vectors synchronously here to keep 2724 /* TODO: dump the hash bucket vectors synchronously here to keep
2726 them as close to the hash table as possible. */ 2725 them as close to the hash table as possible. */
2727 DUMP_FIELD_COPY (out, hash, count);
2728 DUMP_FIELD_COPY (out, hash, next_free);
2729 DUMP_FIELD_COPY (out, hash, weakness); 2726 DUMP_FIELD_COPY (out, hash, weakness);
2730 DUMP_FIELD_COPY (out, hash, purecopy); 2727 DUMP_FIELD_COPY (out, hash, purecopy);
2731 DUMP_FIELD_COPY (out, hash, mutable); 2728 DUMP_FIELD_COPY (out, hash, mutable);
2729 DUMP_FIELD_COPY (out, hash, frozen_test);
2732 dump_field_lv (ctx, out, hash, &hash->key_and_value, WEIGHT_STRONG); 2730 dump_field_lv (ctx, out, hash, &hash->key_and_value, WEIGHT_STRONG);
2733 dump_field_lv (ctx, out, hash, &hash->test.name, WEIGHT_STRONG);
2734 dump_field_lv (ctx, out, hash, &hash->test.user_hash_function,
2735 WEIGHT_STRONG);
2736 dump_field_lv (ctx, out, hash, &hash->test.user_cmp_function,
2737 WEIGHT_STRONG);
2738 dump_field_emacs_ptr (ctx, out, hash, &hash->test.cmpfn);
2739 dump_field_emacs_ptr (ctx, out, hash, &hash->test.hashfn);
2740 eassert (hash->next_weak == NULL); 2731 eassert (hash->next_weak == NULL);
2741 return finish_dump_pvec (ctx, &out->header); 2732 return finish_dump_pvec (ctx, &out->header);
2742} 2733}