diff options
| author | Paul Eggert | 2020-08-30 23:40:11 -0700 |
|---|---|---|
| committer | Paul Eggert | 2020-08-31 00:05:56 -0700 |
| commit | 2ff930d861b772466b9f6b95d1776696298f3e0b (patch) | |
| tree | a9591745cd75d73cc9c4573e2e1f3031ef5013ce /src/alloc.c | |
| parent | 886ba068c82dcf5e0e2e1244bf99841d4ff5690c (diff) | |
| download | emacs-2ff930d861b772466b9f6b95d1776696298f3e0b.tar.gz emacs-2ff930d861b772466b9f6b95d1776696298f3e0b.zip | |
Fix GC bug with Lisp floats and --with-wide-int
On --with-wide-int platforms where Lisp_Object can be
put into non-adjacent registers, mark_maybe_pointer failed
to mark a float whose only reference was as a tagged pointer.
* src/alloc.c (live_float_holding): New function,
a generalization of the old live_float_p.
(live_float_p): Use it.
(mark_maybe_pointer): Use live_float_holding, not live_float_p.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 43 |
1 files changed, 31 insertions, 12 deletions
diff --git a/src/alloc.c b/src/alloc.c index b16b2f8b93e..78e0b5f60cc 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -4536,23 +4536,39 @@ live_symbol_p (struct mem_node *m, void *p) | |||
| 4536 | } | 4536 | } |
| 4537 | 4537 | ||
| 4538 | 4538 | ||
| 4539 | /* Return true if P is a pointer to a live Lisp float on | 4539 | /* If P is a (possibly-tagged) pointer to a live Lisp_Float on the |
| 4540 | the heap. M is a pointer to the mem_block for P. */ | 4540 | heap, return the address of the Lisp_Float. Otherwise, return NULL. |
| 4541 | M is a pointer to the mem_block for P. */ | ||
| 4541 | 4542 | ||
| 4542 | static bool | 4543 | static struct Lisp_Float * |
| 4543 | live_float_p (struct mem_node *m, void *p) | 4544 | live_float_holding (struct mem_node *m, void *p) |
| 4544 | { | 4545 | { |
| 4545 | eassert (m->type == MEM_TYPE_FLOAT); | 4546 | eassert (m->type == MEM_TYPE_FLOAT); |
| 4546 | struct float_block *b = m->start; | 4547 | struct float_block *b = m->start; |
| 4547 | char *cp = p; | 4548 | char *cp = p; |
| 4548 | ptrdiff_t offset = cp - (char *) &b->floats[0]; | 4549 | ptrdiff_t offset = cp - (char *) &b->floats[0]; |
| 4549 | 4550 | ||
| 4550 | /* P must point to the start of a Lisp_Float and not be | 4551 | /* P must point to (or be a tagged pointer to) the start of a |
| 4551 | one of the unused cells in the current float block. */ | 4552 | Lisp_Float and not be one of the unused cells in the current |
| 4552 | return (0 <= offset && offset < sizeof b->floats | 4553 | float block. */ |
| 4553 | && offset % sizeof b->floats[0] == 0 | 4554 | if (0 <= offset && offset < sizeof b->floats) |
| 4555 | { | ||
| 4556 | int off = offset % sizeof b->floats[0]; | ||
| 4557 | if ((off == Lisp_Float || off == 0) | ||
| 4554 | && (b != float_block | 4558 | && (b != float_block |
| 4555 | || offset / sizeof b->floats[0] < float_block_index)); | 4559 | || offset / sizeof b->floats[0] < float_block_index)) |
| 4560 | { | ||
| 4561 | p = cp - off; | ||
| 4562 | return p; | ||
| 4563 | } | ||
| 4564 | } | ||
| 4565 | return NULL; | ||
| 4566 | } | ||
| 4567 | |||
| 4568 | static bool | ||
| 4569 | live_float_p (struct mem_node *m, void *p) | ||
| 4570 | { | ||
| 4571 | return live_float_holding (m, p) == p; | ||
| 4556 | } | 4572 | } |
| 4557 | 4573 | ||
| 4558 | /* If P is a pointer to a live, large vector-like object, return the object. | 4574 | /* If P is a pointer to a live, large vector-like object, return the object. |
| @@ -4762,9 +4778,12 @@ mark_maybe_pointer (void *p) | |||
| 4762 | break; | 4778 | break; |
| 4763 | 4779 | ||
| 4764 | case MEM_TYPE_FLOAT: | 4780 | case MEM_TYPE_FLOAT: |
| 4765 | if (! live_float_p (m, p)) | 4781 | { |
| 4766 | return; | 4782 | struct Lisp_Float *h = live_float_holding (m, p); |
| 4767 | obj = make_lisp_ptr (p, Lisp_Float); | 4783 | if (!h) |
| 4784 | return; | ||
| 4785 | obj = make_lisp_ptr (h, Lisp_Float); | ||
| 4786 | } | ||
| 4768 | break; | 4787 | break; |
| 4769 | 4788 | ||
| 4770 | case MEM_TYPE_VECTORLIKE: | 4789 | case MEM_TYPE_VECTORLIKE: |