unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Vibhav Pant <vibhavp@gmail.com>
To: "emacs-devel@gnu.org" <emacs-devel@gnu.org>
Subject: [PATCH] Make purecopy create hash tables properly
Date: Sat, 28 Jan 2017 00:07:05 +0530	[thread overview]
Message-ID: <CA+T2Sh15CUqGRUto5W6O5JGq1kJWj0w07HX9fMxGiCm9JNZ0bA@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 3336 bytes --]

As of now, hash tables are purecopied by getting XVECTOR(table),
and copying the contents to pure-alloced memory[0]. This resulted
in purecopy returning a vector consisting of mostly nil and random numbers[1].

As the current lisp code doesn't use printed hash tables anywhere, this
never caused a problem while dumping emacs. However, using printed
hash tables in any code thats loaded in temacs causes the keys and values
of the table to change [2], or segfaults temacs altogether [3].

The following patch attempts to fix this, by adding a make_pure_hash_table
function that returns a copy of the provided Lisp_Hash_Table* value allocated
in pure space. From my testing, this both the issues with printed hash tables
in temacs, although I am not sure about the repercussions of blindly copying
the header (vectorlike_header) from one Lisp_Hash_Table to another. Any
feedback on this would be appreciated, as I would like to get this into master
to continue work on byte-switch [4], which makes use of printed hash tables
in the constant vector of bytecode functions.

I'm not well versed with Emacs internals, apologies if anything above was
incorrect.

[0] http://git.savannah.gnu.org/cgit/emacs.git/tree/src/alloc.c#n5480
[1] http://ix.io/1ReZ
[2] https://lists.gnu.org/archive/html/emacs-devel/2017-01/msg00568.html
[3] https://lists.gnu.org/archive/html/emacs-devel/2017-01/msg00597.html
[4] http://git.savannah.gnu.org/cgit/emacs.git/tree/etc/TODO#n38
---
diff --git a/src/alloc.c b/src/alloc.c
index f7b6515f4e..b64f2de224 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -5434,6 +5434,33 @@ make_pure_vector (ptrdiff_t len)
   return new;
 }

+static struct Lisp_Hash_Table * make_pure_hash_table(struct
Lisp_Hash_Table *table);
+
+/* Return a hash table with the same parameters and values as that of TABLE
+   allocated from pure space.  */
+static struct Lisp_Hash_Table *
+make_pure_hash_table(struct Lisp_Hash_Table *table)
+{
+  struct Lisp_Hash_Table *pure = pure_alloc (sizeof *pure, Lisp_Vectorlike);
+  pure->header = table->header;
+  pure->weak = purecopy (table->weak);
+  pure->rehash_size = purecopy (table->rehash_size);
+  pure->rehash_threshold = purecopy(table->rehash_threshold);
+  pure->hash = purecopy (table->hash);
+  pure->next = purecopy (table->next);
+  pure->next_free = purecopy (table->next_free);
+  pure->index = purecopy (table->index);
+  pure->count = table->count;
+  pure->key_and_value = purecopy (table->key_and_value);
+  pure->test = table->test;
+
+  if (table->next_weak) {
+    pure->next_weak = make_pure_hash_table (table->next_weak);
+  }
+
+  return pure;
+}
+
 DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0,
        doc: /* Make a copy of object OBJ in pure storage.
 Recursively copies contents of vectors and cons cells.
@@ -5477,7 +5504,11 @@ purecopy (Lisp_Object obj)
     obj = make_pure_string (SSDATA (obj), SCHARS (obj),
     SBYTES (obj),
     STRING_MULTIBYTE (obj));
-  else if (COMPILEDP (obj) || VECTORP (obj) || HASH_TABLE_P (obj))
+  else if (HASH_TABLE_P (obj)) {
+    struct Lisp_Hash_Table *h = make_pure_hash_table(XHASH_TABLE(obj));
+    XSET_HASH_TABLE(obj, h);
+  }
+  else if (COMPILEDP (obj) || VECTORP (obj))
     {
       struct Lisp_Vector *objp = XVECTOR (obj);
       ptrdiff_t nbytes = vector_nbytes (objp);


-- 
Vibhav Pant
vibhavp@gmail.com

[-- Attachment #2: purecopy_hash_table.patch --]
[-- Type: text/x-patch, Size: 1843 bytes --]

diff --git a/src/alloc.c b/src/alloc.c
index f7b6515f4e..b64f2de224 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -5434,6 +5434,33 @@ make_pure_vector (ptrdiff_t len)
   return new;
 }
 
+static struct Lisp_Hash_Table * make_pure_hash_table(struct Lisp_Hash_Table *table);
+
+/* Return a hash table with the same parameters and values as that of TABLE
+   allocated from pure space.  */
+static struct Lisp_Hash_Table *
+make_pure_hash_table(struct Lisp_Hash_Table *table)
+{
+  struct Lisp_Hash_Table *pure = pure_alloc (sizeof *pure, Lisp_Vectorlike);
+  pure->header = table->header;
+  pure->weak = purecopy (table->weak);
+  pure->rehash_size = purecopy (table->rehash_size);
+  pure->rehash_threshold = purecopy(table->rehash_threshold);
+  pure->hash = purecopy (table->hash);
+  pure->next = purecopy (table->next);
+  pure->next_free = purecopy (table->next_free);
+  pure->index = purecopy (table->index);
+  pure->count = table->count;
+  pure->key_and_value = purecopy (table->key_and_value);
+  pure->test = table->test;
+
+  if (table->next_weak) {
+    pure->next_weak = make_pure_hash_table (table->next_weak);
+  }
+
+  return pure;
+}
+
 DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0,
        doc: /* Make a copy of object OBJ in pure storage.
 Recursively copies contents of vectors and cons cells.
@@ -5477,7 +5504,11 @@ purecopy (Lisp_Object obj)
     obj = make_pure_string (SSDATA (obj), SCHARS (obj),
 			    SBYTES (obj),
 			    STRING_MULTIBYTE (obj));
-  else if (COMPILEDP (obj) || VECTORP (obj) || HASH_TABLE_P (obj))
+  else if (HASH_TABLE_P (obj)) {
+    struct Lisp_Hash_Table *h = make_pure_hash_table(XHASH_TABLE(obj));
+    XSET_HASH_TABLE(obj, h);
+  }
+  else if (COMPILEDP (obj) || VECTORP (obj))
     {
       struct Lisp_Vector *objp = XVECTOR (obj);
       ptrdiff_t nbytes = vector_nbytes (objp);

             reply	other threads:[~2017-01-27 18:37 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-27 18:37 Vibhav Pant [this message]
2017-01-27 22:06 ` [PATCH] Make purecopy create hash tables properly Paul Eggert
2017-01-27 23:10 ` Stefan Monnier
2017-01-28 10:25   ` Vibhav Pant
2017-01-28 10:26     ` Vibhav Pant
2017-01-28 14:58     ` Stefan Monnier
2017-01-28 20:06       ` Vibhav Pant
2017-01-29  2:18         ` Stefan Monnier
2017-01-29 17:23       ` Vibhav Pant
2017-01-29 17:58         ` Stefan Monnier
2017-01-29 19:14           ` Vibhav Pant
2017-01-29 19:41             ` Stefan Monnier
2017-01-30 12:43               ` Vibhav Pant

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

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CA+T2Sh15CUqGRUto5W6O5JGq1kJWj0w07HX9fMxGiCm9JNZ0bA@mail.gmail.com \
    --to=vibhavp@gmail.com \
    --cc=emacs-devel@gnu.org \
    /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 public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).