aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2017-02-21 15:31:29 -0800
committerPaul Eggert2017-02-21 15:39:17 -0800
commit5cbdaa98f975c870c4afa24346630a18b55f27ab (patch)
treeb0a776c467e6b1d53fd1e2837305fbc512803df7 /src
parent7207b63c8e290ddec33908ce8d38be5793388318 (diff)
downloademacs-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.c2
-rw-r--r--src/fns.c169
-rw-r--r--src/lisp.h28
-rw-r--r--src/profiler.c10
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;
diff --git a/src/fns.c b/src/fns.c
index 2a6653144bc..3769c4efb70 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -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}
3439static void 3439static void
3440set_hash_next_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val) 3440set_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}
3444static void 3444static void
3445set_hash_hash (struct Lisp_Hash_Table *h, Lisp_Object hash) 3445set_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}
3459static void 3459static void
3460set_hash_index_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val) 3460set_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
3519Lisp_Object 3519static Lisp_Object
3520larger_vector (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max) 3520larger_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
3543Lisp_Object
3544larger_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
3562static ptrdiff_t
3563HASH_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
3571static ptrdiff_t
3572HASH_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)
3775static void 3805static void
3776maybe_resize_hash_table (struct Lisp_Hash_Table *h) 3806maybe_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
3858hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, EMACS_UINT *hash) 3891hash_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,
3922void 3949void
3923hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key) 3950hash_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. */
2055INLINE Lisp_Object
2056HASH_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. */
2062INLINE Lisp_Object 2056INLINE Lisp_Object
2063HASH_HASH (struct Lisp_Hash_Table *h, ptrdiff_t idx) 2057HASH_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. */
2070INLINE Lisp_Object
2071HASH_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. */
2077INLINE ptrdiff_t 2063INLINE ptrdiff_t
2078HASH_TABLE_SIZE (struct Lisp_Hash_Table *h) 2064HASH_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. */