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