diff options
Diffstat (limited to 'src/fns.c')
| -rw-r--r-- | src/fns.c | 53 |
1 files changed, 33 insertions, 20 deletions
| @@ -4474,7 +4474,7 @@ hashfn_eql (Lisp_Object key, struct Lisp_Hash_Table *h) | |||
| 4474 | /* Given H, return a hash code for KEY which uses a user-defined | 4474 | /* Given H, return a hash code for KEY which uses a user-defined |
| 4475 | function to compare keys. */ | 4475 | function to compare keys. */ |
| 4476 | 4476 | ||
| 4477 | Lisp_Object | 4477 | static Lisp_Object |
| 4478 | hashfn_user_defined (Lisp_Object key, struct Lisp_Hash_Table *h) | 4478 | hashfn_user_defined (Lisp_Object key, struct Lisp_Hash_Table *h) |
| 4479 | { | 4479 | { |
| 4480 | Lisp_Object args[] = { h->test.user_hash_function, key }; | 4480 | Lisp_Object args[] = { h->test.user_hash_function, key }; |
| @@ -4638,11 +4638,10 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) | |||
| 4638 | if (h->next_free < 0) | 4638 | if (h->next_free < 0) |
| 4639 | { | 4639 | { |
| 4640 | ptrdiff_t old_size = HASH_TABLE_SIZE (h); | 4640 | ptrdiff_t old_size = HASH_TABLE_SIZE (h); |
| 4641 | EMACS_INT new_size; | 4641 | /* FIXME: better growth management, ditch std_rehash_size */ |
| 4642 | 4642 | EMACS_INT new_size = old_size * std_rehash_size; | |
| 4643 | double float_new_size = old_size * std_rehash_size; | 4643 | if (new_size < EMACS_INT_MAX) |
| 4644 | if (float_new_size < EMACS_INT_MAX) | 4644 | new_size = max (new_size, 32); /* avoid slow initial growth */ |
| 4645 | new_size = float_new_size; | ||
| 4646 | else | 4645 | else |
| 4647 | new_size = EMACS_INT_MAX; | 4646 | new_size = EMACS_INT_MAX; |
| 4648 | if (PTRDIFF_MAX < new_size) | 4647 | if (PTRDIFF_MAX < new_size) |
| @@ -4691,20 +4690,39 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) | |||
| 4691 | } | 4690 | } |
| 4692 | } | 4691 | } |
| 4693 | 4692 | ||
| 4694 | /* Recompute the hashes (and hence also the "next" pointers). | 4693 | static const struct hash_table_test * |
| 4695 | Normally there's never a need to recompute hashes. | 4694 | hash_table_test_from_std (hash_table_std_test_t test) |
| 4696 | This is done only on first access to a hash-table loaded from | 4695 | { |
| 4697 | the "pdump", because the objects' addresses may have changed, thus | 4696 | switch (test) |
| 4698 | affecting their hashes. */ | 4697 | { |
| 4698 | case Test_eq: return &hashtest_eq; | ||
| 4699 | case Test_eql: return &hashtest_eql; | ||
| 4700 | case Test_equal: return &hashtest_equal; | ||
| 4701 | } | ||
| 4702 | emacs_abort(); | ||
| 4703 | } | ||
| 4704 | |||
| 4705 | /* Rebuild a hash table from its frozen (dumped) form. */ | ||
| 4699 | void | 4706 | void |
| 4700 | hash_table_rehash (Lisp_Object hash) | 4707 | hash_table_thaw (Lisp_Object hash_table) |
| 4701 | { | 4708 | { |
| 4702 | struct Lisp_Hash_Table *h = XHASH_TABLE (hash); | 4709 | struct Lisp_Hash_Table *h = XHASH_TABLE (hash_table); |
| 4703 | ptrdiff_t i, count = h->count; | 4710 | |
| 4711 | /* Freezing discarded most non-essential information; recompute it. | ||
| 4712 | The allocation is minimal with no room for growth. */ | ||
| 4713 | h->test = *hash_table_test_from_std (h->frozen_test); | ||
| 4714 | ptrdiff_t size = ASIZE (h->key_and_value) / 2; | ||
| 4715 | h->count = size; | ||
| 4716 | ptrdiff_t index_size = hash_index_size (size); | ||
| 4717 | h->next_free = -1; | ||
| 4718 | |||
| 4719 | h->hash = make_nil_vector (size); | ||
| 4720 | h->next = make_vector (size, make_fixnum (-1)); | ||
| 4721 | h->index = make_vector (index_size, make_fixnum (-1)); | ||
| 4704 | 4722 | ||
| 4705 | /* Recompute the actual hash codes for each entry in the table. | 4723 | /* Recompute the actual hash codes for each entry in the table. |
| 4706 | Order is still invalid. */ | 4724 | Order is still invalid. */ |
| 4707 | for (i = 0; i < count; i++) | 4725 | for (ptrdiff_t i = 0; i < size; i++) |
| 4708 | { | 4726 | { |
| 4709 | Lisp_Object key = HASH_KEY (h, i); | 4727 | Lisp_Object key = HASH_KEY (h, i); |
| 4710 | Lisp_Object hash_code = hash_from_key (h, key); | 4728 | Lisp_Object hash_code = hash_from_key (h, key); |
| @@ -4712,12 +4730,7 @@ hash_table_rehash (Lisp_Object hash) | |||
| 4712 | set_hash_hash_slot (h, i, hash_code); | 4730 | set_hash_hash_slot (h, i, hash_code); |
| 4713 | set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket)); | 4731 | set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket)); |
| 4714 | set_hash_index_slot (h, start_of_bucket, i); | 4732 | set_hash_index_slot (h, start_of_bucket, i); |
| 4715 | eassert (HASH_NEXT (h, i) != i); /* Stop loops. */ | ||
| 4716 | } | 4733 | } |
| 4717 | |||
| 4718 | ptrdiff_t size = ASIZE (h->next); | ||
| 4719 | for (; i + 1 < size; i++) | ||
| 4720 | set_hash_next_slot (h, i, i + 1); | ||
| 4721 | } | 4734 | } |
| 4722 | 4735 | ||
| 4723 | /* Lookup KEY in hash table H. If HASH is non-null, return in *HASH | 4736 | /* Lookup KEY in hash table H. If HASH is non-null, return in *HASH |