aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert2020-08-30 23:40:11 -0700
committerPaul Eggert2020-08-31 00:05:56 -0700
commit2ff930d861b772466b9f6b95d1776696298f3e0b (patch)
treea9591745cd75d73cc9c4573e2e1f3031ef5013ce /src/alloc.c
parent886ba068c82dcf5e0e2e1244bf99841d4ff5690c (diff)
downloademacs-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.c43
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
4542static bool 4543static struct Lisp_Float *
4543live_float_p (struct mem_node *m, void *p) 4544live_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
4568static bool
4569live_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: