aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert2020-09-05 12:13:32 -0700
committerPaul Eggert2020-09-05 12:15:14 -0700
commit6cf62141c4467314f67c2ef75a4bf94d41ff050f (patch)
tree15e690c820576893cb9ca5d3f2dd1455dd3f0520 /src/alloc.c
parent940ea1549117f56642fd6830bdbccf8865a932bb (diff)
downloademacs-6cf62141c4467314f67c2ef75a4bf94d41ff050f.tar.gz
emacs-6cf62141c4467314f67c2ef75a4bf94d41ff050f.zip
Reinstall recent GC-related changes
The report that they broke macOS was a false alarm, as the previous commit was also broken (Bug#43152#62). * src/alloc.c (live_string_holding, live_cons_holding) (live_symbol_holding): Count only pointers that point to a struct component, or are a tagged pointer to the start of the struct. Exception: for non-bool-vector pseudovectors, count any pointer past the header, since it’s too much of a pain to write code for every pseudovector. (live_float_holding, live_vector_pointer): New functions, which are similar about counting pointers. (live_float_p, live_large_vector_holding) (live_small_vector_pointer, mark_maybe_pointer): Use them. (mark_maybe_object, mark_maybe_objects): Remove, and remove all callers; mark_maybe_pointer now suffices. (mark_objects): New function. * src/alloc.c (mark_vectorlike, mark_face_cache): * src/eval.c (mark_specpdl): * src/fringe.c (mark_fringe_data): * src/keyboard.c (mark_kboards): Simplify by using mark_objects. * src/lisp.h (SAFE_ALLOCA_LISP_EXTRA): Clear any Lisp_Object arrays large enough to not fit into the stack, so that GC need not worry about whether they contain objects.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c247
1 files changed, 118 insertions, 129 deletions
diff --git a/src/alloc.c b/src/alloc.c
index b16b2f8b93e..b12922b5858 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -4457,9 +4457,17 @@ live_string_holding (struct mem_node *m, void *p)
4457 must not be on the free-list. */ 4457 must not be on the free-list. */
4458 if (0 <= offset && offset < sizeof b->strings) 4458 if (0 <= offset && offset < sizeof b->strings)
4459 { 4459 {
4460 struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0]; 4460 ptrdiff_t off = offset % sizeof b->strings[0];
4461 if (s->u.s.data) 4461 if (off == Lisp_String
4462 return s; 4462 || off == 0
4463 || off == offsetof (struct Lisp_String, u.s.size_byte)
4464 || off == offsetof (struct Lisp_String, u.s.intervals)
4465 || off == offsetof (struct Lisp_String, u.s.data))
4466 {
4467 struct Lisp_String *s = p = cp -= off;
4468 if (s->u.s.data)
4469 return s;
4470 }
4463 } 4471 }
4464 return NULL; 4472 return NULL;
4465} 4473}
@@ -4489,9 +4497,15 @@ live_cons_holding (struct mem_node *m, void *p)
4489 && (b != cons_block 4497 && (b != cons_block
4490 || offset / sizeof b->conses[0] < cons_block_index)) 4498 || offset / sizeof b->conses[0] < cons_block_index))
4491 { 4499 {
4492 struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0]; 4500 ptrdiff_t off = offset % sizeof b->conses[0];
4493 if (!deadp (s->u.s.car)) 4501 if (off == Lisp_Cons
4494 return s; 4502 || off == 0
4503 || off == offsetof (struct Lisp_Cons, u.s.u.cdr))
4504 {
4505 struct Lisp_Cons *s = p = cp -= off;
4506 if (!deadp (s->u.s.car))
4507 return s;
4508 }
4495 } 4509 }
4496 return NULL; 4510 return NULL;
4497} 4511}
@@ -4522,9 +4536,23 @@ live_symbol_holding (struct mem_node *m, void *p)
4522 && (b != symbol_block 4536 && (b != symbol_block
4523 || offset / sizeof b->symbols[0] < symbol_block_index)) 4537 || offset / sizeof b->symbols[0] < symbol_block_index))
4524 { 4538 {
4525 struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0]; 4539 ptrdiff_t off = offset % sizeof b->symbols[0];
4526 if (!deadp (s->u.s.function)) 4540 if (off == Lisp_Symbol
4527 return s; 4541
4542 /* Plain '|| off == 0' would run afoul of GCC 10.2
4543 -Wlogical-op, as Lisp_Symbol happens to be zero. */
4544 || (Lisp_Symbol != 0 && off == 0)
4545
4546 || off == offsetof (struct Lisp_Symbol, u.s.name)
4547 || off == offsetof (struct Lisp_Symbol, u.s.val)
4548 || off == offsetof (struct Lisp_Symbol, u.s.function)
4549 || off == offsetof (struct Lisp_Symbol, u.s.plist)
4550 || off == offsetof (struct Lisp_Symbol, u.s.next))
4551 {
4552 struct Lisp_Symbol *s = p = cp -= off;
4553 if (!deadp (s->u.s.function))
4554 return s;
4555 }
4528 } 4556 }
4529 return NULL; 4557 return NULL;
4530} 4558}
@@ -4536,23 +4564,70 @@ live_symbol_p (struct mem_node *m, void *p)
4536} 4564}
4537 4565
4538 4566
4539/* Return true if P is a pointer to a live Lisp float on 4567/* 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. */ 4568 heap, return the address of the Lisp_Float. Otherwise, return NULL.
4569 M is a pointer to the mem_block for P. */
4541 4570
4542static bool 4571static struct Lisp_Float *
4543live_float_p (struct mem_node *m, void *p) 4572live_float_holding (struct mem_node *m, void *p)
4544{ 4573{
4545 eassert (m->type == MEM_TYPE_FLOAT); 4574 eassert (m->type == MEM_TYPE_FLOAT);
4546 struct float_block *b = m->start; 4575 struct float_block *b = m->start;
4547 char *cp = p; 4576 char *cp = p;
4548 ptrdiff_t offset = cp - (char *) &b->floats[0]; 4577 ptrdiff_t offset = cp - (char *) &b->floats[0];
4549 4578
4550 /* P must point to the start of a Lisp_Float and not be 4579 /* 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. */ 4580 Lisp_Float and not be one of the unused cells in the current
4552 return (0 <= offset && offset < sizeof b->floats 4581 float block. */
4553 && offset % sizeof b->floats[0] == 0 4582 if (0 <= offset && offset < sizeof b->floats)
4583 {
4584 int off = offset % sizeof b->floats[0];
4585 if ((off == Lisp_Float || off == 0)
4554 && (b != float_block 4586 && (b != float_block
4555 || offset / sizeof b->floats[0] < float_block_index)); 4587 || offset / sizeof b->floats[0] < float_block_index))
4588 {
4589 p = cp - off;
4590 return p;
4591 }
4592 }
4593 return NULL;
4594}
4595
4596static bool
4597live_float_p (struct mem_node *m, void *p)
4598{
4599 return live_float_holding (m, p) == p;
4600}
4601
4602/* Return VECTOR if P points within it, NULL otherwise. */
4603
4604static struct Lisp_Vector *
4605live_vector_pointer (struct Lisp_Vector *vector, void *p)
4606{
4607 void *vvector = vector;
4608 char *cvector = vvector;
4609 char *cp = p;
4610 ptrdiff_t offset = cp - cvector;
4611 return ((offset == Lisp_Vectorlike
4612 || offset == 0
4613 || (sizeof vector->header <= offset
4614 && offset < vector_nbytes (vector)
4615 && (! (vector->header.size & PSEUDOVECTOR_FLAG)
4616 ? (offsetof (struct Lisp_Vector, contents) <= offset
4617 && (((offset - offsetof (struct Lisp_Vector, contents))
4618 % word_size)
4619 == 0))
4620 /* For non-bool-vector pseudovectors, treat any pointer
4621 past the header as valid since it's too much of a pain
4622 to write special-case code for every pseudovector. */
4623 : (! PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR)
4624 || offset == offsetof (struct Lisp_Bool_Vector, size)
4625 || (offsetof (struct Lisp_Bool_Vector, data) <= offset
4626 && (((offset
4627 - offsetof (struct Lisp_Bool_Vector, data))
4628 % sizeof (bits_word))
4629 == 0))))))
4630 ? vector : NULL);
4556} 4631}
4557 4632
4558/* If P is a pointer to a live, large vector-like object, return the object. 4633/* If P is a pointer to a live, large vector-like object, return the object.
@@ -4563,10 +4638,7 @@ static struct Lisp_Vector *
4563live_large_vector_holding (struct mem_node *m, void *p) 4638live_large_vector_holding (struct mem_node *m, void *p)
4564{ 4639{
4565 eassert (m->type == MEM_TYPE_VECTORLIKE); 4640 eassert (m->type == MEM_TYPE_VECTORLIKE);
4566 struct Lisp_Vector *vp = p; 4641 return live_vector_pointer (large_vector_vec (m->start), p);
4567 struct Lisp_Vector *vector = large_vector_vec (m->start);
4568 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
4569 return vector <= vp && vp < next ? vector : NULL;
4570} 4642}
4571 4643
4572static bool 4644static bool
@@ -4596,7 +4668,7 @@ live_small_vector_holding (struct mem_node *m, void *p)
4596 { 4668 {
4597 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector)); 4669 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
4598 if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE)) 4670 if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
4599 return vector; 4671 return live_vector_pointer (vector, vp);
4600 vector = next; 4672 vector = next;
4601 } 4673 }
4602 return NULL; 4674 return NULL;
@@ -4608,117 +4680,33 @@ live_small_vector_p (struct mem_node *m, void *p)
4608 return live_small_vector_holding (m, p) == p; 4680 return live_small_vector_holding (m, p) == p;
4609} 4681}
4610 4682
4611/* Mark OBJ if we can prove it's a Lisp_Object. */ 4683/* If P points to Lisp data, mark that as live if it isn't already
4684 marked. */
4612 4685
4613static void 4686static void
4614mark_maybe_object (Lisp_Object obj) 4687mark_maybe_pointer (void *p)
4615{ 4688{
4689 struct mem_node *m;
4690
4616#if USE_VALGRIND 4691#if USE_VALGRIND
4617 VALGRIND_MAKE_MEM_DEFINED (&obj, sizeof (obj)); 4692 VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p));
4618#endif 4693#endif
4619 4694
4620 int type_tag = XTYPE (obj);
4621 intptr_t pointer_word_tag = LISP_WORD_TAG (type_tag), offset, ipo;
4622
4623 switch (type_tag)
4624 {
4625 case_Lisp_Int: case Lisp_Type_Unused0:
4626 return;
4627
4628 case Lisp_Symbol:
4629 offset = (intptr_t) lispsym;
4630 break;
4631
4632 default:
4633 offset = 0;
4634 break;
4635 }
4636
4637 INT_ADD_WRAPV ((intptr_t) XLP (obj), offset - pointer_word_tag, &ipo);
4638 void *po = (void *) ipo;
4639
4640 /* If the pointer is in the dump image and the dump has a record 4695 /* If the pointer is in the dump image and the dump has a record
4641 of the object starting at the place where the pointer points, we 4696 of the object starting at the place where the pointer points, we
4642 definitely have an object. If the pointer is in the dump image 4697 definitely have an object. If the pointer is in the dump image
4643 and the dump has no idea what the pointer is pointing at, we 4698 and the dump has no idea what the pointer is pointing at, we
4644 definitely _don't_ have an object. */ 4699 definitely _don't_ have an object. */
4645 if (pdumper_object_p (po)) 4700 if (pdumper_object_p (p))
4646 { 4701 {
4647 /* Don't use pdumper_object_p_precise here! It doesn't check the 4702 /* Don't use pdumper_object_p_precise here! It doesn't check the
4648 tag bits. OBJ here might be complete garbage, so we need to 4703 tag bits. OBJ here might be complete garbage, so we need to
4649 verify both the pointer and the tag. */ 4704 verify both the pointer and the tag. */
4650 if (pdumper_find_object_type (po) == type_tag)
4651 mark_object (obj);
4652 return;
4653 }
4654
4655 struct mem_node *m = mem_find (po);
4656
4657 if (m != MEM_NIL)
4658 {
4659 bool mark_p = false;
4660
4661 switch (type_tag)
4662 {
4663 case Lisp_String:
4664 mark_p = m->type == MEM_TYPE_STRING && live_string_p (m, po);
4665 break;
4666
4667 case Lisp_Cons:
4668 mark_p = m->type == MEM_TYPE_CONS && live_cons_p (m, po);
4669 break;
4670
4671 case Lisp_Symbol:
4672 mark_p = m->type == MEM_TYPE_SYMBOL && live_symbol_p (m, po);
4673 break;
4674
4675 case Lisp_Float:
4676 mark_p = m->type == MEM_TYPE_FLOAT && live_float_p (m, po);
4677 break;
4678
4679 case Lisp_Vectorlike:
4680 mark_p = (m->type == MEM_TYPE_VECTOR_BLOCK
4681 ? live_small_vector_p (m, po)
4682 : (m->type == MEM_TYPE_VECTORLIKE
4683 && live_large_vector_p (m, po)));
4684 break;
4685
4686 default:
4687 eassume (false);
4688 }
4689
4690 if (mark_p)
4691 mark_object (obj);
4692 }
4693}
4694
4695void
4696mark_maybe_objects (Lisp_Object const *array, ptrdiff_t nelts)
4697{
4698 for (Lisp_Object const *lim = array + nelts; array < lim; array++)
4699 mark_maybe_object (*array);
4700}
4701
4702/* If P points to Lisp data, mark that as live if it isn't already
4703 marked. */
4704
4705static void
4706mark_maybe_pointer (void *p)
4707{
4708 struct mem_node *m;
4709
4710#if USE_VALGRIND
4711 VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p));
4712#endif
4713
4714 if (pdumper_object_p (p))
4715 {
4716 int type = pdumper_find_object_type (p); 4705 int type = pdumper_find_object_type (p);
4717 if (pdumper_valid_object_type_p (type)) 4706 if (pdumper_valid_object_type_p (type))
4718 mark_object (type == Lisp_Symbol 4707 mark_object (type == Lisp_Symbol
4719 ? make_lisp_symbol (p) 4708 ? make_lisp_symbol (p)
4720 : make_lisp_ptr (p, type)); 4709 : make_lisp_ptr (p, type));
4721 /* See mark_maybe_object for why we can confidently return. */
4722 return; 4710 return;
4723 } 4711 }
4724 4712
@@ -4762,9 +4750,12 @@ mark_maybe_pointer (void *p)
4762 break; 4750 break;
4763 4751
4764 case MEM_TYPE_FLOAT: 4752 case MEM_TYPE_FLOAT:
4765 if (! live_float_p (m, p)) 4753 {
4766 return; 4754 struct Lisp_Float *h = live_float_holding (m, p);
4767 obj = make_lisp_ptr (p, Lisp_Float); 4755 if (!h)
4756 return;
4757 obj = make_lisp_ptr (h, Lisp_Float);
4758 }
4768 break; 4759 break;
4769 4760
4770 case MEM_TYPE_VECTORLIKE: 4761 case MEM_TYPE_VECTORLIKE:
@@ -4849,11 +4840,6 @@ mark_memory (void const *start, void const *end)
4849 intptr_t ip; 4840 intptr_t ip;
4850 INT_ADD_WRAPV ((intptr_t) p, (intptr_t) lispsym, &ip); 4841 INT_ADD_WRAPV ((intptr_t) p, (intptr_t) lispsym, &ip);
4851 mark_maybe_pointer ((void *) ip); 4842 mark_maybe_pointer ((void *) ip);
4852
4853 verify (alignof (Lisp_Object) % GC_POINTER_ALIGNMENT == 0);
4854 if (alignof (Lisp_Object) == GC_POINTER_ALIGNMENT
4855 || (uintptr_t) pp % alignof (Lisp_Object) == 0)
4856 mark_maybe_object (*(Lisp_Object const *) pp);
4857 } 4843 }
4858} 4844}
4859 4845
@@ -6261,7 +6247,6 @@ mark_vectorlike (union vectorlike_header *header)
6261{ 6247{
6262 struct Lisp_Vector *ptr = (struct Lisp_Vector *) header; 6248 struct Lisp_Vector *ptr = (struct Lisp_Vector *) header;
6263 ptrdiff_t size = ptr->header.size; 6249 ptrdiff_t size = ptr->header.size;
6264 ptrdiff_t i;
6265 6250
6266 eassert (!vector_marked_p (ptr)); 6251 eassert (!vector_marked_p (ptr));
6267 6252
@@ -6276,8 +6261,7 @@ mark_vectorlike (union vectorlike_header *header)
6276 the number of Lisp_Object fields that we should trace. 6261 the number of Lisp_Object fields that we should trace.
6277 The distinction is used e.g. by Lisp_Process which places extra 6262 The distinction is used e.g. by Lisp_Process which places extra
6278 non-Lisp_Object fields at the end of the structure... */ 6263 non-Lisp_Object fields at the end of the structure... */
6279 for (i = 0; i < size; i++) /* ...and then mark its elements. */ 6264 mark_objects (ptr->contents, size);
6280 mark_object (ptr->contents[i]);
6281} 6265}
6282 6266
6283/* Like mark_vectorlike but optimized for char-tables (and 6267/* Like mark_vectorlike but optimized for char-tables (and
@@ -6376,8 +6360,7 @@ mark_face_cache (struct face_cache *c)
6376{ 6360{
6377 if (c) 6361 if (c)
6378 { 6362 {
6379 int i, j; 6363 for (int i = 0; i < c->used; i++)
6380 for (i = 0; i < c->used; ++i)
6381 { 6364 {
6382 struct face *face = FACE_FROM_ID_OR_NULL (c->f, i); 6365 struct face *face = FACE_FROM_ID_OR_NULL (c->f, i);
6383 6366
@@ -6386,8 +6369,7 @@ mark_face_cache (struct face_cache *c)
6386 if (face->font && !vectorlike_marked_p (&face->font->header)) 6369 if (face->font && !vectorlike_marked_p (&face->font->header))
6387 mark_vectorlike (&face->font->header); 6370 mark_vectorlike (&face->font->header);
6388 6371
6389 for (j = 0; j < LFACE_VECTOR_SIZE; ++j) 6372 mark_objects (face->lface, LFACE_VECTOR_SIZE);
6390 mark_object (face->lface[j]);
6391 } 6373 }
6392 } 6374 }
6393 } 6375 }
@@ -6500,6 +6482,13 @@ mark_hash_table (struct Lisp_Vector *ptr)
6500 } 6482 }
6501} 6483}
6502 6484
6485void
6486mark_objects (Lisp_Object *obj, ptrdiff_t n)
6487{
6488 for (ptrdiff_t i = 0; i < n; i++)
6489 mark_object (obj[i]);
6490}
6491
6503/* Determine type of generic Lisp_Object and mark it accordingly. 6492/* Determine type of generic Lisp_Object and mark it accordingly.
6504 6493
6505 This function implements a straightforward depth-first marking 6494 This function implements a straightforward depth-first marking