unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* [PATCH] Make purecopy create hash tables properly
@ 2017-01-27 18:37 Vibhav Pant
  2017-01-27 22:06 ` Paul Eggert
  2017-01-27 23:10 ` Stefan Monnier
  0 siblings, 2 replies; 13+ messages in thread
From: Vibhav Pant @ 2017-01-27 18:37 UTC (permalink / raw
  To: emacs-devel@gnu.org

[-- 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);

^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2017-01-30 12:43 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-27 18:37 [PATCH] Make purecopy create hash tables properly Vibhav Pant
2017-01-27 22:06 ` 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

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).