diff options
| author | Vibhav Pant | 2017-01-30 12:03:23 +0530 |
|---|---|---|
| committer | Vibhav Pant | 2017-01-30 12:03:23 +0530 |
| commit | 9c4dfdd1af9f97c6a8d7e922b68a39052116790c (patch) | |
| tree | 1fb54fcb7d5eaa61ed88ea67ee9d17fde112bc4a /src/alloc.c | |
| parent | 8ba236e772b64d0bb021aa691bd7eacf4b7f3ae4 (diff) | |
| download | emacs-9c4dfdd1af9f97c6a8d7e922b68a39052116790c.tar.gz emacs-9c4dfdd1af9f97c6a8d7e922b68a39052116790c.zip | |
Fix hash tables not being purified correctly.
* src/alloc.c
(purecopy_hash_table) New function, makes a copy of the given hash
table in pure storage.
Add new struct `pinned_object' and `pinned_objects' linked list for
pinning objects.
(Fpurecopy) Allow purifying hash tables
(purecopy) Pin hash tables that are either weak or not declared with
`:purecopy t`, use purecopy_hash_table otherwise.
(marked_pinned_objects) New function, marks all objects in pinned_objects.
(garbage_collect_1) Use it. Mark all pinned objects before sweeping.
* src/lisp.h Add new field `pure' to struct `Lisp_Hash_Table'.
* src/fns.c: Add `purecopy' parameter to hash tables.
(Fmake_hash_table): Check for a `:purecopy PURECOPY' argument, pass it
to make_hash_table.
(make_hash_table): Add `pure' parameter, set h->pure to it.
(Fclrhash, Fremhash, Fputhash): Enforce that the table is impure with
CHECK_IMPURE.
* src/lread.c: (read1) Parse for `purecopy' parameter while reading
hash tables.
* src/print.c: (print_object) add the `purecopy' parameter while
printing hash tables.
* src/category.c, src/emacs-module.c, src/image.c, src/profiler.c,
src/xterm.c: Use new (make_hash_table).
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 76 |
1 files changed, 73 insertions, 3 deletions
diff --git a/src/alloc.c b/src/alloc.c index f7b6515f4e7..dd2b688f91e 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -5434,6 +5434,37 @@ make_pure_vector (ptrdiff_t len) | |||
| 5434 | return new; | 5434 | return new; |
| 5435 | } | 5435 | } |
| 5436 | 5436 | ||
| 5437 | /* Copy all contents and parameters of TABLE to a new table allocated | ||
| 5438 | from pure space, return the purified table. */ | ||
| 5439 | static struct Lisp_Hash_Table * | ||
| 5440 | purecopy_hash_table (struct Lisp_Hash_Table *table) { | ||
| 5441 | eassert (NILP (table->weak)); | ||
| 5442 | eassert (!NILP (table->pure)); | ||
| 5443 | |||
| 5444 | struct Lisp_Hash_Table *pure = pure_alloc (sizeof *pure, Lisp_Vectorlike); | ||
| 5445 | struct hash_table_test pure_test = table->test; | ||
| 5446 | |||
| 5447 | /* Purecopy the hash table test. */ | ||
| 5448 | pure_test.name = purecopy (table->test.name); | ||
| 5449 | pure_test.user_hash_function = purecopy (table->test.user_hash_function); | ||
| 5450 | pure_test.user_cmp_function = purecopy (table->test.user_cmp_function); | ||
| 5451 | |||
| 5452 | pure->test = pure_test; | ||
| 5453 | pure->header = table->header; | ||
| 5454 | pure->weak = purecopy (Qnil); | ||
| 5455 | pure->rehash_size = purecopy (table->rehash_size); | ||
| 5456 | pure->rehash_threshold = purecopy (table->rehash_threshold); | ||
| 5457 | pure->hash = purecopy (table->hash); | ||
| 5458 | pure->next = purecopy (table->next); | ||
| 5459 | pure->next_free = purecopy (table->next_free); | ||
| 5460 | pure->index = purecopy (table->index); | ||
| 5461 | pure->count = table->count; | ||
| 5462 | pure->key_and_value = purecopy (table->key_and_value); | ||
| 5463 | pure->pure = purecopy (table->pure); | ||
| 5464 | |||
| 5465 | return pure; | ||
| 5466 | } | ||
| 5467 | |||
| 5437 | DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0, | 5468 | DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0, |
| 5438 | doc: /* Make a copy of object OBJ in pure storage. | 5469 | doc: /* Make a copy of object OBJ in pure storage. |
| 5439 | Recursively copies contents of vectors and cons cells. | 5470 | Recursively copies contents of vectors and cons cells. |
| @@ -5442,14 +5473,22 @@ Does not copy symbols. Copies strings without text properties. */) | |||
| 5442 | { | 5473 | { |
| 5443 | if (NILP (Vpurify_flag)) | 5474 | if (NILP (Vpurify_flag)) |
| 5444 | return obj; | 5475 | return obj; |
| 5445 | else if (MARKERP (obj) || OVERLAYP (obj) | 5476 | else if (MARKERP (obj) || OVERLAYP (obj) || SYMBOLP (obj)) |
| 5446 | || HASH_TABLE_P (obj) || SYMBOLP (obj)) | ||
| 5447 | /* Can't purify those. */ | 5477 | /* Can't purify those. */ |
| 5448 | return obj; | 5478 | return obj; |
| 5449 | else | 5479 | else |
| 5450 | return purecopy (obj); | 5480 | return purecopy (obj); |
| 5451 | } | 5481 | } |
| 5452 | 5482 | ||
| 5483 | struct pinned_object | ||
| 5484 | { | ||
| 5485 | Lisp_Object object; | ||
| 5486 | struct pinned_object *next; | ||
| 5487 | }; | ||
| 5488 | |||
| 5489 | /* Pinned objects are marked before every GC cycle. */ | ||
| 5490 | static struct pinned_object *pinned_objects; | ||
| 5491 | |||
| 5453 | static Lisp_Object | 5492 | static Lisp_Object |
| 5454 | purecopy (Lisp_Object obj) | 5493 | purecopy (Lisp_Object obj) |
| 5455 | { | 5494 | { |
| @@ -5477,7 +5516,27 @@ purecopy (Lisp_Object obj) | |||
| 5477 | obj = make_pure_string (SSDATA (obj), SCHARS (obj), | 5516 | obj = make_pure_string (SSDATA (obj), SCHARS (obj), |
| 5478 | SBYTES (obj), | 5517 | SBYTES (obj), |
| 5479 | STRING_MULTIBYTE (obj)); | 5518 | STRING_MULTIBYTE (obj)); |
| 5480 | else if (COMPILEDP (obj) || VECTORP (obj) || HASH_TABLE_P (obj)) | 5519 | else if (HASH_TABLE_P (obj)) |
| 5520 | { | ||
| 5521 | struct Lisp_Hash_Table *table = XHASH_TABLE (obj); | ||
| 5522 | /* We cannot purify hash tables which haven't been defined with | ||
| 5523 | :purecopy as non-nil or are weak - they aren't guaranteed to | ||
| 5524 | not change. */ | ||
| 5525 | if (!NILP (table->weak) || NILP (table->pure)) | ||
| 5526 | { | ||
| 5527 | /* Instead, the hash table is added to the list of pinned objects, | ||
| 5528 | and is marked before GC. */ | ||
| 5529 | struct pinned_object *o = xmalloc (sizeof *o); | ||
| 5530 | o->object = obj; | ||
| 5531 | o->next = pinned_objects; | ||
| 5532 | pinned_objects = o; | ||
| 5533 | return obj; /* Don't hash cons it. */ | ||
| 5534 | } | ||
| 5535 | |||
| 5536 | struct Lisp_Hash_Table *h = purecopy_hash_table (table); | ||
| 5537 | XSET_HASH_TABLE (obj, h); | ||
| 5538 | } | ||
| 5539 | else if (COMPILEDP (obj) || VECTORP (obj)) | ||
| 5481 | { | 5540 | { |
| 5482 | struct Lisp_Vector *objp = XVECTOR (obj); | 5541 | struct Lisp_Vector *objp = XVECTOR (obj); |
| 5483 | ptrdiff_t nbytes = vector_nbytes (objp); | 5542 | ptrdiff_t nbytes = vector_nbytes (objp); |
| @@ -5694,6 +5753,16 @@ compact_undo_list (Lisp_Object list) | |||
| 5694 | } | 5753 | } |
| 5695 | 5754 | ||
| 5696 | static void | 5755 | static void |
| 5756 | mark_pinned_objects (void) | ||
| 5757 | { | ||
| 5758 | struct pinned_object *pobj; | ||
| 5759 | for (pobj = pinned_objects; pobj; pobj = pobj->next) | ||
| 5760 | { | ||
| 5761 | mark_object (pobj->object); | ||
| 5762 | } | ||
| 5763 | } | ||
| 5764 | |||
| 5765 | static void | ||
| 5697 | mark_pinned_symbols (void) | 5766 | mark_pinned_symbols (void) |
| 5698 | { | 5767 | { |
| 5699 | struct symbol_block *sblk; | 5768 | struct symbol_block *sblk; |
| @@ -5813,6 +5882,7 @@ garbage_collect_1 (void *end) | |||
| 5813 | for (i = 0; i < staticidx; i++) | 5882 | for (i = 0; i < staticidx; i++) |
| 5814 | mark_object (*staticvec[i]); | 5883 | mark_object (*staticvec[i]); |
| 5815 | 5884 | ||
| 5885 | mark_pinned_objects (); | ||
| 5816 | mark_pinned_symbols (); | 5886 | mark_pinned_symbols (); |
| 5817 | mark_terminals (); | 5887 | mark_terminals (); |
| 5818 | mark_kboards (); | 5888 | mark_kboards (); |