diff options
| author | Paul Eggert | 2017-02-21 15:31:29 -0800 |
|---|---|---|
| committer | Paul Eggert | 2017-02-21 15:39:17 -0800 |
| commit | 5cbdaa98f975c870c4afa24346630a18b55f27ab (patch) | |
| tree | b0a776c467e6b1d53fd1e2837305fbc512803df7 /src | |
| parent | 7207b63c8e290ddec33908ce8d38be5793388318 (diff) | |
| download | emacs-5cbdaa98f975c870c4afa24346630a18b55f27ab.tar.gz emacs-5cbdaa98f975c870c4afa24346630a18b55f27ab.zip | |
Use ptrdiff_t instead of Lisp_Object for collision
* src/alloc.c (purecopy_hash_table): Assign, don’t purecopy.
* src/fns.c (set_hash_next_slot, set_hash_index_slot): Hash index
arg is now ptrdiff_t index (or -1 if empty), not Lisp_Object
integer (or Qnil if empty). All callers changed.
(larger_vecalloc): New static function.
(larger_vector): Use it.
(HASH_NEXT, HASH_INDEX): Move here from lisp.h. Return ptrdiff_t
index (or -1) not Lisp_Object integer (or Qnil). All callers changed.
* src/fns.c (make_hash_table, maybe_resize_hash_table, hash_lookup)
(hash_put, hash_remove_from_table, hash_clear, sweep_weak_table):
* src/profiler.c (evict_lower_half, record_backtrace):
-1, not nil, is now the convention for end of collision list.
* src/fns.c (maybe_resize_hash_table): Avoid double-initialization
of the free list. Reallocate H->next last, in case other
reallocations exhaust memory.
* src/lisp.h (struct Lisp_Hash_Table): ‘next_free’ is now
ptrdiff_t, not Lisp_Object. Adjust commentary for ‘next’ and
‘index’, which no longer contain nil.
(HASH_NEXT, HASH_INDEX): Move to src/fns.c.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 2 | ||||
| -rw-r--r-- | src/fns.c | 169 | ||||
| -rw-r--r-- | src/lisp.h | 28 | ||||
| -rw-r--r-- | src/profiler.c | 10 |
4 files changed, 106 insertions, 103 deletions
diff --git a/src/alloc.c b/src/alloc.c index b579e7ed1ae..5da4290701e 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -5459,7 +5459,7 @@ purecopy_hash_table (struct Lisp_Hash_Table *table) | |||
| 5459 | pure->rehash_size = purecopy (table->rehash_size); | 5459 | pure->rehash_size = purecopy (table->rehash_size); |
| 5460 | pure->hash = purecopy (table->hash); | 5460 | pure->hash = purecopy (table->hash); |
| 5461 | pure->next = purecopy (table->next); | 5461 | pure->next = purecopy (table->next); |
| 5462 | pure->next_free = purecopy (table->next_free); | 5462 | pure->next_free = table->next_free; |
| 5463 | pure->index = purecopy (table->index); | 5463 | pure->index = purecopy (table->index); |
| 5464 | pure->count = table->count; | 5464 | pure->count = table->count; |
| 5465 | pure->pure = table->pure; | 5465 | pure->pure = table->pure; |
| @@ -3437,9 +3437,9 @@ set_hash_next (struct Lisp_Hash_Table *h, Lisp_Object next) | |||
| 3437 | h->next = next; | 3437 | h->next = next; |
| 3438 | } | 3438 | } |
| 3439 | static void | 3439 | static void |
| 3440 | set_hash_next_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val) | 3440 | set_hash_next_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, ptrdiff_t val) |
| 3441 | { | 3441 | { |
| 3442 | gc_aset (h->next, idx, val); | 3442 | gc_aset (h->next, idx, make_number (val)); |
| 3443 | } | 3443 | } |
| 3444 | static void | 3444 | static void |
| 3445 | set_hash_hash (struct Lisp_Hash_Table *h, Lisp_Object hash) | 3445 | set_hash_hash (struct Lisp_Hash_Table *h, Lisp_Object hash) |
| @@ -3457,9 +3457,9 @@ set_hash_index (struct Lisp_Hash_Table *h, Lisp_Object index) | |||
| 3457 | h->index = index; | 3457 | h->index = index; |
| 3458 | } | 3458 | } |
| 3459 | static void | 3459 | static void |
| 3460 | set_hash_index_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val) | 3460 | set_hash_index_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, ptrdiff_t val) |
| 3461 | { | 3461 | { |
| 3462 | gc_aset (h->index, idx, val); | 3462 | gc_aset (h->index, idx, make_number (val)); |
| 3463 | } | 3463 | } |
| 3464 | 3464 | ||
| 3465 | /* If OBJ is a Lisp hash table, return a pointer to its struct | 3465 | /* If OBJ is a Lisp hash table, return a pointer to its struct |
| @@ -3513,11 +3513,11 @@ get_key_arg (Lisp_Object key, ptrdiff_t nargs, Lisp_Object *args, char *used) | |||
| 3513 | /* Return a Lisp vector which has the same contents as VEC but has | 3513 | /* Return a Lisp vector which has the same contents as VEC but has |
| 3514 | at least INCR_MIN more entries, where INCR_MIN is positive. | 3514 | at least INCR_MIN more entries, where INCR_MIN is positive. |
| 3515 | If NITEMS_MAX is not -1, do not grow the vector to be any larger | 3515 | If NITEMS_MAX is not -1, do not grow the vector to be any larger |
| 3516 | than NITEMS_MAX. Entries in the resulting | 3516 | than NITEMS_MAX. New entries in the resulting vector are |
| 3517 | vector that are not copied from VEC are set to nil. */ | 3517 | uninitialized. */ |
| 3518 | 3518 | ||
| 3519 | Lisp_Object | 3519 | static Lisp_Object |
| 3520 | larger_vector (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max) | 3520 | larger_vecalloc (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max) |
| 3521 | { | 3521 | { |
| 3522 | struct Lisp_Vector *v; | 3522 | struct Lisp_Vector *v; |
| 3523 | ptrdiff_t incr, incr_max, old_size, new_size; | 3523 | ptrdiff_t incr, incr_max, old_size, new_size; |
| @@ -3534,16 +3534,46 @@ larger_vector (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max) | |||
| 3534 | new_size = old_size + incr; | 3534 | new_size = old_size + incr; |
| 3535 | v = allocate_vector (new_size); | 3535 | v = allocate_vector (new_size); |
| 3536 | memcpy (v->contents, XVECTOR (vec)->contents, old_size * sizeof *v->contents); | 3536 | memcpy (v->contents, XVECTOR (vec)->contents, old_size * sizeof *v->contents); |
| 3537 | memclear (v->contents + old_size, incr * word_size); | ||
| 3538 | XSETVECTOR (vec, v); | 3537 | XSETVECTOR (vec, v); |
| 3539 | return vec; | 3538 | return vec; |
| 3540 | } | 3539 | } |
| 3541 | 3540 | ||
| 3541 | /* Likewise, except set new entries in the resulting vector to nil. */ | ||
| 3542 | |||
| 3543 | Lisp_Object | ||
| 3544 | larger_vector (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max) | ||
| 3545 | { | ||
| 3546 | ptrdiff_t old_size = ASIZE (vec); | ||
| 3547 | Lisp_Object v = larger_vecalloc (vec, incr_min, nitems_max); | ||
| 3548 | ptrdiff_t new_size = ASIZE (v); | ||
| 3549 | memclear (XVECTOR (v)->contents + old_size, | ||
| 3550 | (new_size - old_size) * word_size); | ||
| 3551 | return v; | ||
| 3552 | } | ||
| 3553 | |||
| 3542 | 3554 | ||
| 3543 | /*********************************************************************** | 3555 | /*********************************************************************** |
| 3544 | Low-level Functions | 3556 | Low-level Functions |
| 3545 | ***********************************************************************/ | 3557 | ***********************************************************************/ |
| 3546 | 3558 | ||
| 3559 | /* Return the index of the next entry in H following the one at IDX, | ||
| 3560 | or -1 if none. */ | ||
| 3561 | |||
| 3562 | static ptrdiff_t | ||
| 3563 | HASH_NEXT (struct Lisp_Hash_Table *h, ptrdiff_t idx) | ||
| 3564 | { | ||
| 3565 | return XINT (AREF (h->next, idx)); | ||
| 3566 | } | ||
| 3567 | |||
| 3568 | /* Return the index of the element in hash table H that is the start | ||
| 3569 | of the collision list at index IDX, or -1 if the list is empty. */ | ||
| 3570 | |||
| 3571 | static ptrdiff_t | ||
| 3572 | HASH_INDEX (struct Lisp_Hash_Table *h, ptrdiff_t idx) | ||
| 3573 | { | ||
| 3574 | return XINT (AREF (h->index, idx)); | ||
| 3575 | } | ||
| 3576 | |||
| 3547 | /* Compare KEY1 which has hash code HASH1 and KEY2 with hash code | 3577 | /* Compare KEY1 which has hash code HASH1 and KEY2 with hash code |
| 3548 | HASH2 in hash table H using `eql'. Value is true if KEY1 and | 3578 | HASH2 in hash table H using `eql'. Value is true if KEY1 and |
| 3549 | KEY2 are the same. */ | 3579 | KEY2 are the same. */ |
| @@ -3715,14 +3745,14 @@ make_hash_table (struct hash_table_test test, | |||
| 3715 | h->count = 0; | 3745 | h->count = 0; |
| 3716 | h->key_and_value = Fmake_vector (make_number (2 * sz), Qnil); | 3746 | h->key_and_value = Fmake_vector (make_number (2 * sz), Qnil); |
| 3717 | h->hash = Fmake_vector (size, Qnil); | 3747 | h->hash = Fmake_vector (size, Qnil); |
| 3718 | h->next = Fmake_vector (size, Qnil); | 3748 | h->next = Fmake_vector (size, make_number (-1)); |
| 3719 | h->index = Fmake_vector (make_number (index_size), Qnil); | 3749 | h->index = Fmake_vector (make_number (index_size), make_number (-1)); |
| 3720 | h->pure = pure; | 3750 | h->pure = pure; |
| 3721 | 3751 | ||
| 3722 | /* Set up the free list. */ | 3752 | /* Set up the free list. */ |
| 3723 | for (i = 0; i < sz - 1; ++i) | 3753 | for (i = 0; i < sz - 1; ++i) |
| 3724 | set_hash_next_slot (h, i, make_number (i + 1)); | 3754 | set_hash_next_slot (h, i, i + 1); |
| 3725 | h->next_free = make_number (0); | 3755 | h->next_free = 0; |
| 3726 | 3756 | ||
| 3727 | XSET_HASH_TABLE (table, h); | 3757 | XSET_HASH_TABLE (table, h); |
| 3728 | eassert (HASH_TABLE_P (table)); | 3758 | eassert (HASH_TABLE_P (table)); |
| @@ -3775,7 +3805,7 @@ copy_hash_table (struct Lisp_Hash_Table *h1) | |||
| 3775 | static void | 3805 | static void |
| 3776 | maybe_resize_hash_table (struct Lisp_Hash_Table *h) | 3806 | maybe_resize_hash_table (struct Lisp_Hash_Table *h) |
| 3777 | { | 3807 | { |
| 3778 | if (NILP (h->next_free)) | 3808 | if (h->next_free < 0) |
| 3779 | { | 3809 | { |
| 3780 | ptrdiff_t old_size = HASH_TABLE_SIZE (h); | 3810 | ptrdiff_t old_size = HASH_TABLE_SIZE (h); |
| 3781 | EMACS_INT new_size, index_size, nsize; | 3811 | EMACS_INT new_size, index_size, nsize; |
| @@ -3813,29 +3843,32 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) | |||
| 3813 | 3843 | ||
| 3814 | set_hash_key_and_value (h, larger_vector (h->key_and_value, | 3844 | set_hash_key_and_value (h, larger_vector (h->key_and_value, |
| 3815 | 2 * (new_size - old_size), -1)); | 3845 | 2 * (new_size - old_size), -1)); |
| 3816 | set_hash_next (h, larger_vector (h->next, new_size - old_size, -1)); | ||
| 3817 | set_hash_hash (h, larger_vector (h->hash, new_size - old_size, -1)); | 3846 | set_hash_hash (h, larger_vector (h->hash, new_size - old_size, -1)); |
| 3818 | set_hash_index (h, Fmake_vector (make_number (index_size), Qnil)); | 3847 | set_hash_index (h, Fmake_vector (make_number (index_size), |
| 3848 | make_number (-1))); | ||
| 3849 | set_hash_next (h, larger_vecalloc (h->next, new_size - old_size, -1)); | ||
| 3819 | 3850 | ||
| 3820 | /* Update the free list. Do it so that new entries are added at | 3851 | /* Update the free list. Do it so that new entries are added at |
| 3821 | the end of the free list. This makes some operations like | 3852 | the end of the free list. This makes some operations like |
| 3822 | maphash faster. */ | 3853 | maphash faster. */ |
| 3823 | for (i = old_size; i < new_size - 1; ++i) | 3854 | for (i = old_size; i < new_size - 1; ++i) |
| 3824 | set_hash_next_slot (h, i, make_number (i + 1)); | 3855 | set_hash_next_slot (h, i, i + 1); |
| 3856 | set_hash_next_slot (h, i, -1); | ||
| 3825 | 3857 | ||
| 3826 | if (!NILP (h->next_free)) | 3858 | if (h->next_free < 0) |
| 3859 | h->next_free = old_size; | ||
| 3860 | else | ||
| 3827 | { | 3861 | { |
| 3828 | Lisp_Object last, next; | 3862 | ptrdiff_t last = h->next_free; |
| 3829 | 3863 | while (true) | |
| 3830 | last = h->next_free; | 3864 | { |
| 3831 | while (next = HASH_NEXT (h, XFASTINT (last)), | 3865 | ptrdiff_t next = HASH_NEXT (h, last); |
| 3832 | !NILP (next)) | 3866 | if (next < 0) |
| 3833 | last = next; | 3867 | break; |
| 3834 | 3868 | last = next; | |
| 3835 | set_hash_next_slot (h, XFASTINT (last), make_number (old_size)); | 3869 | } |
| 3870 | set_hash_next_slot (h, last, old_size); | ||
| 3836 | } | 3871 | } |
| 3837 | else | ||
| 3838 | XSETFASTINT (h->next_free, old_size); | ||
| 3839 | 3872 | ||
| 3840 | /* Rehash. */ | 3873 | /* Rehash. */ |
| 3841 | for (i = 0; i < old_size; ++i) | 3874 | for (i = 0; i < old_size; ++i) |
| @@ -3844,7 +3877,7 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) | |||
| 3844 | EMACS_UINT hash_code = XUINT (HASH_HASH (h, i)); | 3877 | EMACS_UINT hash_code = XUINT (HASH_HASH (h, i)); |
| 3845 | ptrdiff_t start_of_bucket = hash_code % ASIZE (h->index); | 3878 | ptrdiff_t start_of_bucket = hash_code % ASIZE (h->index); |
| 3846 | set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket)); | 3879 | set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket)); |
| 3847 | set_hash_index_slot (h, start_of_bucket, make_number (i)); | 3880 | set_hash_index_slot (h, start_of_bucket, i); |
| 3848 | } | 3881 | } |
| 3849 | } | 3882 | } |
| 3850 | } | 3883 | } |
| @@ -3858,8 +3891,7 @@ ptrdiff_t | |||
| 3858 | hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, EMACS_UINT *hash) | 3891 | hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, EMACS_UINT *hash) |
| 3859 | { | 3892 | { |
| 3860 | EMACS_UINT hash_code; | 3893 | EMACS_UINT hash_code; |
| 3861 | ptrdiff_t start_of_bucket; | 3894 | ptrdiff_t start_of_bucket, i; |
| 3862 | Lisp_Object idx; | ||
| 3863 | 3895 | ||
| 3864 | hash_code = h->test.hashfn (&h->test, key); | 3896 | hash_code = h->test.hashfn (&h->test, key); |
| 3865 | eassert ((hash_code & ~INTMASK) == 0); | 3897 | eassert ((hash_code & ~INTMASK) == 0); |
| @@ -3867,20 +3899,15 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, EMACS_UINT *hash) | |||
| 3867 | *hash = hash_code; | 3899 | *hash = hash_code; |
| 3868 | 3900 | ||
| 3869 | start_of_bucket = hash_code % ASIZE (h->index); | 3901 | start_of_bucket = hash_code % ASIZE (h->index); |
| 3870 | idx = HASH_INDEX (h, start_of_bucket); | ||
| 3871 | 3902 | ||
| 3872 | while (!NILP (idx)) | 3903 | for (i = HASH_INDEX (h, start_of_bucket); 0 <= i; i = HASH_NEXT (h, i)) |
| 3873 | { | 3904 | if (EQ (key, HASH_KEY (h, i)) |
| 3874 | ptrdiff_t i = XFASTINT (idx); | 3905 | || (h->test.cmpfn |
| 3875 | if (EQ (key, HASH_KEY (h, i)) | 3906 | && hash_code == XUINT (HASH_HASH (h, i)) |
| 3876 | || (h->test.cmpfn | 3907 | && h->test.cmpfn (&h->test, key, HASH_KEY (h, i)))) |
| 3877 | && hash_code == XUINT (HASH_HASH (h, i)) | 3908 | break; |
| 3878 | && h->test.cmpfn (&h->test, key, HASH_KEY (h, i)))) | ||
| 3879 | break; | ||
| 3880 | idx = HASH_NEXT (h, i); | ||
| 3881 | } | ||
| 3882 | 3909 | ||
| 3883 | return NILP (idx) ? -1 : XFASTINT (idx); | 3910 | return i; |
| 3884 | } | 3911 | } |
| 3885 | 3912 | ||
| 3886 | 3913 | ||
| @@ -3901,7 +3928,7 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value, | |||
| 3901 | h->count++; | 3928 | h->count++; |
| 3902 | 3929 | ||
| 3903 | /* Store key/value in the key_and_value vector. */ | 3930 | /* Store key/value in the key_and_value vector. */ |
| 3904 | i = XFASTINT (h->next_free); | 3931 | i = h->next_free; |
| 3905 | h->next_free = HASH_NEXT (h, i); | 3932 | h->next_free = HASH_NEXT (h, i); |
| 3906 | set_hash_key_slot (h, i, key); | 3933 | set_hash_key_slot (h, i, key); |
| 3907 | set_hash_value_slot (h, i, value); | 3934 | set_hash_value_slot (h, i, value); |
| @@ -3912,7 +3939,7 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value, | |||
| 3912 | /* Add new entry to its collision chain. */ | 3939 | /* Add new entry to its collision chain. */ |
| 3913 | start_of_bucket = hash % ASIZE (h->index); | 3940 | start_of_bucket = hash % ASIZE (h->index); |
| 3914 | set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket)); | 3941 | set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket)); |
| 3915 | set_hash_index_slot (h, start_of_bucket, make_number (i)); | 3942 | set_hash_index_slot (h, start_of_bucket, i); |
| 3916 | return i; | 3943 | return i; |
| 3917 | } | 3944 | } |
| 3918 | 3945 | ||
| @@ -3922,30 +3949,25 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value, | |||
| 3922 | void | 3949 | void |
| 3923 | hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key) | 3950 | hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key) |
| 3924 | { | 3951 | { |
| 3925 | EMACS_UINT hash_code; | 3952 | EMACS_UINT hash_code = h->test.hashfn (&h->test, key); |
| 3926 | ptrdiff_t start_of_bucket; | ||
| 3927 | Lisp_Object idx, prev; | ||
| 3928 | |||
| 3929 | hash_code = h->test.hashfn (&h->test, key); | ||
| 3930 | eassert ((hash_code & ~INTMASK) == 0); | 3953 | eassert ((hash_code & ~INTMASK) == 0); |
| 3931 | start_of_bucket = hash_code % ASIZE (h->index); | 3954 | ptrdiff_t start_of_bucket = hash_code % ASIZE (h->index); |
| 3932 | idx = HASH_INDEX (h, start_of_bucket); | 3955 | ptrdiff_t prev = -1; |
| 3933 | prev = Qnil; | ||
| 3934 | 3956 | ||
| 3935 | while (!NILP (idx)) | 3957 | for (ptrdiff_t i = HASH_INDEX (h, start_of_bucket); |
| 3958 | 0 <= i; | ||
| 3959 | i = HASH_NEXT (h, i)) | ||
| 3936 | { | 3960 | { |
| 3937 | ptrdiff_t i = XFASTINT (idx); | ||
| 3938 | |||
| 3939 | if (EQ (key, HASH_KEY (h, i)) | 3961 | if (EQ (key, HASH_KEY (h, i)) |
| 3940 | || (h->test.cmpfn | 3962 | || (h->test.cmpfn |
| 3941 | && hash_code == XUINT (HASH_HASH (h, i)) | 3963 | && hash_code == XUINT (HASH_HASH (h, i)) |
| 3942 | && h->test.cmpfn (&h->test, key, HASH_KEY (h, i)))) | 3964 | && h->test.cmpfn (&h->test, key, HASH_KEY (h, i)))) |
| 3943 | { | 3965 | { |
| 3944 | /* Take entry out of collision chain. */ | 3966 | /* Take entry out of collision chain. */ |
| 3945 | if (NILP (prev)) | 3967 | if (prev < 0) |
| 3946 | set_hash_index_slot (h, start_of_bucket, HASH_NEXT (h, i)); | 3968 | set_hash_index_slot (h, start_of_bucket, HASH_NEXT (h, i)); |
| 3947 | else | 3969 | else |
| 3948 | set_hash_next_slot (h, XFASTINT (prev), HASH_NEXT (h, i)); | 3970 | set_hash_next_slot (h, prev, HASH_NEXT (h, i)); |
| 3949 | 3971 | ||
| 3950 | /* Clear slots in key_and_value and add the slots to | 3972 | /* Clear slots in key_and_value and add the slots to |
| 3951 | the free list. */ | 3973 | the free list. */ |
| @@ -3953,16 +3975,13 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key) | |||
| 3953 | set_hash_value_slot (h, i, Qnil); | 3975 | set_hash_value_slot (h, i, Qnil); |
| 3954 | set_hash_hash_slot (h, i, Qnil); | 3976 | set_hash_hash_slot (h, i, Qnil); |
| 3955 | set_hash_next_slot (h, i, h->next_free); | 3977 | set_hash_next_slot (h, i, h->next_free); |
| 3956 | h->next_free = make_number (i); | 3978 | h->next_free = i; |
| 3957 | h->count--; | 3979 | h->count--; |
| 3958 | eassert (h->count >= 0); | 3980 | eassert (h->count >= 0); |
| 3959 | break; | 3981 | break; |
| 3960 | } | 3982 | } |
| 3961 | else | 3983 | |
| 3962 | { | 3984 | prev = i; |
| 3963 | prev = idx; | ||
| 3964 | idx = HASH_NEXT (h, i); | ||
| 3965 | } | ||
| 3966 | } | 3985 | } |
| 3967 | } | 3986 | } |
| 3968 | 3987 | ||
| @@ -3978,16 +3997,16 @@ hash_clear (struct Lisp_Hash_Table *h) | |||
| 3978 | 3997 | ||
| 3979 | for (i = 0; i < size; ++i) | 3998 | for (i = 0; i < size; ++i) |
| 3980 | { | 3999 | { |
| 3981 | set_hash_next_slot (h, i, i < size - 1 ? make_number (i + 1) : Qnil); | 4000 | set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1); |
| 3982 | set_hash_key_slot (h, i, Qnil); | 4001 | set_hash_key_slot (h, i, Qnil); |
| 3983 | set_hash_value_slot (h, i, Qnil); | 4002 | set_hash_value_slot (h, i, Qnil); |
| 3984 | set_hash_hash_slot (h, i, Qnil); | 4003 | set_hash_hash_slot (h, i, Qnil); |
| 3985 | } | 4004 | } |
| 3986 | 4005 | ||
| 3987 | for (i = 0; i < ASIZE (h->index); ++i) | 4006 | for (i = 0; i < ASIZE (h->index); ++i) |
| 3988 | ASET (h->index, i, Qnil); | 4007 | ASET (h->index, i, make_number (-1)); |
| 3989 | 4008 | ||
| 3990 | h->next_free = make_number (0); | 4009 | h->next_free = 0; |
| 3991 | h->count = 0; | 4010 | h->count = 0; |
| 3992 | } | 4011 | } |
| 3993 | } | 4012 | } |
| @@ -4011,14 +4030,12 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p) | |||
| 4011 | 4030 | ||
| 4012 | for (ptrdiff_t bucket = 0; bucket < n; ++bucket) | 4031 | for (ptrdiff_t bucket = 0; bucket < n; ++bucket) |
| 4013 | { | 4032 | { |
| 4014 | Lisp_Object idx, next, prev; | ||
| 4015 | |||
| 4016 | /* Follow collision chain, removing entries that | 4033 | /* Follow collision chain, removing entries that |
| 4017 | don't survive this garbage collection. */ | 4034 | don't survive this garbage collection. */ |
| 4018 | prev = Qnil; | 4035 | ptrdiff_t prev = -1; |
| 4019 | for (idx = HASH_INDEX (h, bucket); !NILP (idx); idx = next) | 4036 | ptrdiff_t next; |
| 4037 | for (ptrdiff_t i = HASH_INDEX (h, bucket); 0 <= i; i = next) | ||
| 4020 | { | 4038 | { |
| 4021 | ptrdiff_t i = XFASTINT (idx); | ||
| 4022 | bool key_known_to_survive_p = survives_gc_p (HASH_KEY (h, i)); | 4039 | bool key_known_to_survive_p = survives_gc_p (HASH_KEY (h, i)); |
| 4023 | bool value_known_to_survive_p = survives_gc_p (HASH_VALUE (h, i)); | 4040 | bool value_known_to_survive_p = survives_gc_p (HASH_VALUE (h, i)); |
| 4024 | bool remove_p; | 4041 | bool remove_p; |
| @@ -4041,14 +4058,14 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p) | |||
| 4041 | if (remove_p) | 4058 | if (remove_p) |
| 4042 | { | 4059 | { |
| 4043 | /* Take out of collision chain. */ | 4060 | /* Take out of collision chain. */ |
| 4044 | if (NILP (prev)) | 4061 | if (prev < 0) |
| 4045 | set_hash_index_slot (h, bucket, next); | 4062 | set_hash_index_slot (h, bucket, next); |
| 4046 | else | 4063 | else |
| 4047 | set_hash_next_slot (h, XFASTINT (prev), next); | 4064 | set_hash_next_slot (h, prev, next); |
| 4048 | 4065 | ||
| 4049 | /* Add to free list. */ | 4066 | /* Add to free list. */ |
| 4050 | set_hash_next_slot (h, i, h->next_free); | 4067 | set_hash_next_slot (h, i, h->next_free); |
| 4051 | h->next_free = idx; | 4068 | h->next_free = i; |
| 4052 | 4069 | ||
| 4053 | /* Clear key, value, and hash. */ | 4070 | /* Clear key, value, and hash. */ |
| 4054 | set_hash_key_slot (h, i, Qnil); | 4071 | set_hash_key_slot (h, i, Qnil); |
| @@ -4059,7 +4076,7 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p) | |||
| 4059 | } | 4076 | } |
| 4060 | else | 4077 | else |
| 4061 | { | 4078 | { |
| 4062 | prev = idx; | 4079 | prev = i; |
| 4063 | } | 4080 | } |
| 4064 | } | 4081 | } |
| 4065 | else | 4082 | else |
diff --git a/src/lisp.h b/src/lisp.h index 6e0252621a6..027fd07d720 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -1980,13 +1980,12 @@ struct Lisp_Hash_Table | |||
| 1980 | 1980 | ||
| 1981 | /* Vector used to chain entries. If entry I is free, next[I] is the | 1981 | /* Vector used to chain entries. If entry I is free, next[I] is the |
| 1982 | entry number of the next free item. If entry I is non-free, | 1982 | entry number of the next free item. If entry I is non-free, |
| 1983 | next[I] is the index of the next entry in the collision chain. */ | 1983 | next[I] is the index of the next entry in the collision chain, |
| 1984 | or -1 if there is such entry. */ | ||
| 1984 | Lisp_Object next; | 1985 | Lisp_Object next; |
| 1985 | 1986 | ||
| 1986 | /* Index of first free entry in free list. */ | 1987 | /* Bucket vector. An entry of -1 indicates no item is present, |
| 1987 | Lisp_Object next_free; | 1988 | and a nonnegative entry is the index of the first item in |
| 1988 | |||
| 1989 | /* Bucket vector. A non-nil entry is the index of the first item in | ||
| 1990 | a collision chain. This vector's size can be larger than the | 1989 | a collision chain. This vector's size can be larger than the |
| 1991 | hash table size to reduce collisions. */ | 1990 | hash table size to reduce collisions. */ |
| 1992 | Lisp_Object index; | 1991 | Lisp_Object index; |
| @@ -1998,6 +1997,9 @@ struct Lisp_Hash_Table | |||
| 1998 | /* Number of key/value entries in the table. */ | 1997 | /* Number of key/value entries in the table. */ |
| 1999 | ptrdiff_t count; | 1998 | ptrdiff_t count; |
| 2000 | 1999 | ||
| 2000 | /* Index of first free entry in free list, or -1 if none. */ | ||
| 2001 | ptrdiff_t next_free; | ||
| 2002 | |||
| 2001 | /* True if the table can be purecopied. The table cannot be | 2003 | /* True if the table can be purecopied. The table cannot be |
| 2002 | changed afterwards. */ | 2004 | changed afterwards. */ |
| 2003 | bool pure; | 2005 | bool pure; |
| @@ -2050,14 +2052,6 @@ HASH_VALUE (struct Lisp_Hash_Table *h, ptrdiff_t idx) | |||
| 2050 | return AREF (h->key_and_value, 2 * idx + 1); | 2052 | return AREF (h->key_and_value, 2 * idx + 1); |
| 2051 | } | 2053 | } |
| 2052 | 2054 | ||
| 2053 | /* Value is the index of the next entry following the one at IDX | ||
| 2054 | in hash table H. */ | ||
| 2055 | INLINE Lisp_Object | ||
| 2056 | HASH_NEXT (struct Lisp_Hash_Table *h, ptrdiff_t idx) | ||
| 2057 | { | ||
| 2058 | return AREF (h->next, idx); | ||
| 2059 | } | ||
| 2060 | |||
| 2061 | /* Value is the hash code computed for entry IDX in hash table H. */ | 2055 | /* Value is the hash code computed for entry IDX in hash table H. */ |
| 2062 | INLINE Lisp_Object | 2056 | INLINE Lisp_Object |
| 2063 | HASH_HASH (struct Lisp_Hash_Table *h, ptrdiff_t idx) | 2057 | HASH_HASH (struct Lisp_Hash_Table *h, ptrdiff_t idx) |
| @@ -2065,14 +2059,6 @@ HASH_HASH (struct Lisp_Hash_Table *h, ptrdiff_t idx) | |||
| 2065 | return AREF (h->hash, idx); | 2059 | return AREF (h->hash, idx); |
| 2066 | } | 2060 | } |
| 2067 | 2061 | ||
| 2068 | /* Value is the index of the element in hash table H that is the | ||
| 2069 | start of the collision list at index IDX in the index vector of H. */ | ||
| 2070 | INLINE Lisp_Object | ||
| 2071 | HASH_INDEX (struct Lisp_Hash_Table *h, ptrdiff_t idx) | ||
| 2072 | { | ||
| 2073 | return AREF (h->index, idx); | ||
| 2074 | } | ||
| 2075 | |||
| 2076 | /* Value is the size of hash table H. */ | 2062 | /* Value is the size of hash table H. */ |
| 2077 | INLINE ptrdiff_t | 2063 | INLINE ptrdiff_t |
| 2078 | HASH_TABLE_SIZE (struct Lisp_Hash_Table *h) | 2064 | HASH_TABLE_SIZE (struct Lisp_Hash_Table *h) |
diff --git a/src/profiler.c b/src/profiler.c index edc28fc8427..08ef6ee9623 100644 --- a/src/profiler.c +++ b/src/profiler.c | |||
| @@ -119,7 +119,7 @@ static void evict_lower_half (log_t *log) | |||
| 119 | XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr. */ | 119 | XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr. */ |
| 120 | Fremhash (key, tmp); | 120 | Fremhash (key, tmp); |
| 121 | } | 121 | } |
| 122 | eassert (EQ (log->next_free, make_number (i))); | 122 | eassert (log->next_free == i); |
| 123 | 123 | ||
| 124 | eassert (VECTORP (key)); | 124 | eassert (VECTORP (key)); |
| 125 | for (ptrdiff_t j = 0; j < ASIZE (key); j++) | 125 | for (ptrdiff_t j = 0; j < ASIZE (key); j++) |
| @@ -139,11 +139,11 @@ record_backtrace (log_t *log, EMACS_INT count) | |||
| 139 | Lisp_Object backtrace; | 139 | Lisp_Object backtrace; |
| 140 | ptrdiff_t index; | 140 | ptrdiff_t index; |
| 141 | 141 | ||
| 142 | if (!INTEGERP (log->next_free)) | 142 | if (log->next_free < 0) |
| 143 | /* FIXME: transfer the evicted counts to a special entry rather | 143 | /* FIXME: transfer the evicted counts to a special entry rather |
| 144 | than dropping them on the floor. */ | 144 | than dropping them on the floor. */ |
| 145 | evict_lower_half (log); | 145 | evict_lower_half (log); |
| 146 | index = XINT (log->next_free); | 146 | index = log->next_free; |
| 147 | 147 | ||
| 148 | /* Get a "working memory" vector. */ | 148 | /* Get a "working memory" vector. */ |
| 149 | backtrace = HASH_KEY (log, index); | 149 | backtrace = HASH_KEY (log, index); |
| @@ -163,8 +163,8 @@ record_backtrace (log_t *log, EMACS_INT count) | |||
| 163 | } | 163 | } |
| 164 | else | 164 | else |
| 165 | { /* BEWARE! hash_put in general can allocate memory. | 165 | { /* BEWARE! hash_put in general can allocate memory. |
| 166 | But currently it only does that if log->next_free is nil. */ | 166 | But currently it only does that if log->next_free is -1. */ |
| 167 | eassert (!NILP (log->next_free)); | 167 | eassert (0 <= log->next_free); |
| 168 | ptrdiff_t j = hash_put (log, backtrace, make_number (count), hash); | 168 | ptrdiff_t j = hash_put (log, backtrace, make_number (count), hash); |
| 169 | /* Let's make sure we've put `backtrace' right where it | 169 | /* Let's make sure we've put `backtrace' right where it |
| 170 | already was to start with. */ | 170 | already was to start with. */ |