From: Paul Eggert <eggert@cs.ucla.edu>
To: Pip Cet <pipcet@gmail.com>
Cc: Eli Zaretskii <eliz@gnu.org>,
Daniel Colascione <dancol@dancol.org>,
emacs-devel@gnu.org
Subject: Re: Changes in GC and in pure space (was: [Emacs-diffs] master 5d4dd55: Fix lifetime error in previous patch)
Date: Wed, 21 Aug 2019 19:06:20 -0700 [thread overview]
Message-ID: <397faace-c84b-78e8-1b13-69a10471ffec@cs.ucla.edu> (raw)
In-Reply-To: <CAOqdjBcUnxZGhzHY3kcgvXeh8Hc14Cb580bkzC_wEtQCJdCuhQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 568 bytes --]
Pip Cet wrote:
> (To reproduce the promised segfault, add
>
> (defvar custom-dummy (make-hash-table :test 'eq))
> (puthash custom-dummy custom-dummy custom-dummy)
>
> to custom.el, then rebuild and run (clrhash custom-dummy) in Emacs -Q.
> Trivial to fix, but apparently not obvious enough to have been caught
> in the original changes).
Thanks for reporting that. I installed the attached patch, which should fix that
bug and clean up a few nearby glitches. This patch is a bit less trivial but
should be a smidge faster than the trivial patch would have been.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Fix-clrhash-bug-when-hash-table-needs-rehashing.patch --]
[-- Type: text/x-patch; name="0001-Fix-clrhash-bug-when-hash-table-needs-rehashing.patch", Size: 4348 bytes --]
From ac71011bc1726bd767446407500c20cbbdca74a2 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 21 Aug 2019 18:54:08 -0700
Subject: [PATCH] Fix clrhash bug when hash table needs rehashing
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Problem reported by Pip Cet in:
https://lists.gnu.org/r/emacs-devel/2019-08/msg00316.html
* src/fns.c (maybe_resize_hash_table): Prefer ASET to gc_aset
where either will do. Simplify appending of Qunbound values.
Put index_size calculation closer to where it’s needed.
(hash_clear): If hash_rehash_needed_p (h), don’t clear the
nonexistent hash vector. Use memclear to speed up clearing.
* src/lisp.h (HASH_TABLE_SIZE): Check that the size is positive,
and tell that to the compiler.
---
src/fns.c | 28 ++++++++++++----------------
src/lisp.h | 9 +++++----
2 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/src/fns.c b/src/fns.c
index b606d6299c..8ca0953fe8 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -4198,21 +4198,20 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
new_size);
ptrdiff_t next_size = ASIZE (next);
for (ptrdiff_t i = old_size; i < next_size - 1; i++)
- gc_aset (next, i, make_fixnum (i + 1));
- gc_aset (next, next_size - 1, make_fixnum (-1));
- ptrdiff_t index_size = hash_index_size (h, next_size);
+ ASET (next, i, make_fixnum (i + 1));
+ ASET (next, next_size - 1, make_fixnum (-1));
/* Build the new&larger key_and_value vector, making sure the new
fields are initialized to `unbound`. */
Lisp_Object key_and_value
= larger_vecalloc (h->key_and_value, 2 * (next_size - old_size),
2 * next_size);
- for (ptrdiff_t i = ASIZE (h->key_and_value);
- i < ASIZE (key_and_value); i++)
+ for (ptrdiff_t i = 2 * old_size; i < 2 * next_size; i++)
ASET (key_and_value, i, Qunbound);
Lisp_Object hash = larger_vector (h->hash, next_size - old_size,
next_size);
+ ptrdiff_t index_size = hash_index_size (h, next_size);
h->index = make_vector (index_size, make_fixnum (-1));
h->key_and_value = key_and_value;
h->hash = hash;
@@ -4404,17 +4403,14 @@ hash_clear (struct Lisp_Hash_Table *h)
{
if (h->count > 0)
{
- ptrdiff_t i, size = HASH_TABLE_SIZE (h);
-
- for (i = 0; i < size; ++i)
- {
- set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1);
- set_hash_key_slot (h, i, Qunbound);
- set_hash_value_slot (h, i, Qnil);
- set_hash_hash_slot (h, i, Qnil);
- }
-
- for (i = 0; i < ASIZE (h->index); ++i)
+ ptrdiff_t size = HASH_TABLE_SIZE (h);
+ if (!hash_rehash_needed_p (h))
+ memclear (XVECTOR (h->hash)->contents, size * word_size);
+ memclear (XVECTOR (h->key_and_value)->contents, size * 2 * word_size);
+ for (ptrdiff_t i = 0; i < size; i++)
+ set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1);
+
+ for (ptrdiff_t i = 0; i < ASIZE (h->index); i++)
ASET (h->index, i, make_fixnum (-1));
h->next_free = 0;
diff --git a/src/lisp.h b/src/lisp.h
index 56ad99b8e3..ae5a81e7b5 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2307,7 +2307,7 @@ #define DEFSYM(sym, name) /* empty */
weakness of the table. */
Lisp_Object weak;
- /* Vector of hash codes.
+ /* Vector of hash codes, or nil if the table needs rehashing.
If the I-th entry is unused, then hash[I] should be nil. */
Lisp_Object hash;
@@ -2327,8 +2327,7 @@ #define DEFSYM(sym, name) /* empty */
'index' are special and are either ignored by the GC or traced in
a special way (e.g. because of weakness). */
- /* Number of key/value entries in the table. This number is
- negated if the table needs rehashing. */
+ /* Number of key/value entries in the table. */
ptrdiff_t count;
/* Index of first free entry in free list, or -1 if none. */
@@ -2413,7 +2412,9 @@ HASH_HASH (const struct Lisp_Hash_Table *h, ptrdiff_t idx)
INLINE ptrdiff_t
HASH_TABLE_SIZE (const struct Lisp_Hash_Table *h)
{
- return ASIZE (h->next);
+ ptrdiff_t size = ASIZE (h->next);
+ eassume (0 < size);
+ return size;
}
void hash_table_rehash (struct Lisp_Hash_Table *h);
--
2.17.1
next prev parent reply other threads:[~2019-08-22 2:06 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20190721193221.1964.53182@vcs0.savannah.gnu.org>
[not found] ` <20190721193222.8C19E20BE2@vcs0.savannah.gnu.org>
2019-07-22 4:12 ` [Emacs-diffs] master 5d4dd55: Fix lifetime error in previous patch Pip Cet
2019-07-22 13:40 ` Stefan Monnier
2019-07-23 1:06 ` Paul Eggert
2019-07-22 15:00 ` Changes in GC and in pure space (was: [Emacs-diffs] master 5d4dd55: Fix lifetime error in previous patch) Eli Zaretskii
2019-07-22 17:47 ` Paul Eggert
2019-07-22 18:19 ` Changes in GC and in pure space Eli Zaretskii
2019-07-22 19:58 ` Stefan Monnier
2019-07-23 1:43 ` Paul Eggert
2019-07-23 14:46 ` Eli Zaretskii
2019-07-23 16:27 ` Paul Eggert
2019-07-23 16:58 ` Eli Zaretskii
2019-07-23 2:25 ` Eli Zaretskii
2019-07-23 1:29 ` bug#36769: portable dumper mishandles user-defined hashtabs Paul Eggert
2019-07-23 2:06 ` Paul Eggert
2019-07-22 19:05 ` Changes in GC and in pure space (was: [Emacs-diffs] master 5d4dd55: Fix lifetime error in previous patch) Pip Cet
2019-07-23 14:56 ` Eli Zaretskii
2019-07-23 15:33 ` Changes in GC and in pure space Stefan Monnier
2019-07-24 3:06 ` Richard Stallman
2019-08-15 9:34 ` Changes in GC and in pure space (was: [Emacs-diffs] master 5d4dd55: Fix lifetime error in previous patch) Paul Eggert
2019-08-16 13:34 ` Pip Cet
2019-08-22 0:25 ` Paul Eggert
2019-08-22 2:06 ` Paul Eggert [this message]
2019-08-22 5:36 ` Paul Eggert
2019-09-04 6:05 ` Paul Eggert
2019-09-04 14:51 ` Eli Zaretskii
2019-09-04 16:56 ` Paul Eggert
2019-09-04 17:36 ` Daniel Colascione
2019-09-04 17:45 ` Changes in GC and in pure space Stefan Monnier
2019-09-04 18:34 ` Óscar Fuentes
2019-09-04 19:15 ` Paul Eggert
2019-09-05 7:04 ` Paul Eggert
2019-07-24 2:58 ` Changes in GC and in pure space (was: [Emacs-diffs] master 5d4dd55: Fix lifetime error in previous patch) Richard Stallman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=397faace-c84b-78e8-1b13-69a10471ffec@cs.ucla.edu \
--to=eggert@cs.ucla.edu \
--cc=dancol@dancol.org \
--cc=eliz@gnu.org \
--cc=emacs-devel@gnu.org \
--cc=pipcet@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.