aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert2020-09-03 12:10:26 -0700
committerPaul Eggert2020-09-03 12:15:09 -0700
commitc47be1b8440883b07b6cf918235a13b65e3d7be6 (patch)
tree8bc1f190dc4d5792d8935425693c5650f9e0253c /src/alloc.c
parentc449a00aa51185486d76ebf602d84e189af702c0 (diff)
downloademacs-c47be1b8440883b07b6cf918235a13b65e3d7be6.tar.gz
emacs-c47be1b8440883b07b6cf918235a13b65e3d7be6.zip
Revert recent GC-related changes (Bug#43152)
* src/alloc.c (live_string_holding, live_cons_holding) (live_symbol_holding, live_large_vector_holding) (live_small_vector_holding): Go back to old approach of treating every would-be pointer to any byte in the object (though not to just past the object end) as addressing the object. (live_float_p): Require that the would-be float point to the start of the Lisp_Float, and not anywhere else. (live_vector_pointer, live_float_holding, mark_objects): Remove. All uses removed. (mark_maybe_object, mark_maybe_objects): Bring back these functions. * src/lisp.h (SAFE_ALLOCA_LISP_EXTRA): Do not clear the new slots, as they're now checked via mark_maybe_objects, not via mark_objects.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c247
1 files changed, 129 insertions, 118 deletions
diff --git a/src/alloc.c b/src/alloc.c
index b12922b5858..b16b2f8b93e 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -4457,17 +4457,9 @@ 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 ptrdiff_t off = offset % sizeof b->strings[0]; 4460 struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0];
4461 if (off == Lisp_String 4461 if (s->u.s.data)
4462 || off == 0 4462 return s;
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 }
4471 } 4463 }
4472 return NULL; 4464 return NULL;
4473} 4465}
@@ -4497,15 +4489,9 @@ live_cons_holding (struct mem_node *m, void *p)
4497 && (b != cons_block 4489 && (b != cons_block
4498 || offset / sizeof b->conses[0] < cons_block_index)) 4490 || offset / sizeof b->conses[0] < cons_block_index))
4499 { 4491 {
4500 ptrdiff_t off = offset % sizeof b->conses[0]; 4492 struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0];
4501 if (off == Lisp_Cons 4493 if (!deadp (s->u.s.car))
4502 || off == 0 4494 return s;
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 }
4509 } 4495 }
4510 return NULL; 4496 return NULL;
4511} 4497}
@@ -4536,23 +4522,9 @@ live_symbol_holding (struct mem_node *m, void *p)
4536 && (b != symbol_block 4522 && (b != symbol_block
4537 || offset / sizeof b->symbols[0] < symbol_block_index)) 4523 || offset / sizeof b->symbols[0] < symbol_block_index))
4538 { 4524 {
4539 ptrdiff_t off = offset % sizeof b->symbols[0]; 4525 struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0];
4540 if (off == Lisp_Symbol 4526 if (!deadp (s->u.s.function))
4541 4527 return s;
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 }
4556 } 4528 }
4557 return NULL; 4529 return NULL;
4558} 4530}
@@ -4564,70 +4536,23 @@ live_symbol_p (struct mem_node *m, void *p)
4564} 4536}
4565 4537
4566 4538
4567/* If P is a (possibly-tagged) pointer to a live Lisp_Float on the 4539/* Return true if P is a pointer to a live Lisp float on
4568 heap, return the address of the Lisp_Float. Otherwise, return NULL. 4540 the heap. M is a pointer to the mem_block for P. */
4569 M is a pointer to the mem_block for P. */
4570 4541
4571static struct Lisp_Float * 4542static bool
4572live_float_holding (struct mem_node *m, void *p) 4543live_float_p (struct mem_node *m, void *p)
4573{ 4544{
4574 eassert (m->type == MEM_TYPE_FLOAT); 4545 eassert (m->type == MEM_TYPE_FLOAT);
4575 struct float_block *b = m->start; 4546 struct float_block *b = m->start;
4576 char *cp = p; 4547 char *cp = p;
4577 ptrdiff_t offset = cp - (char *) &b->floats[0]; 4548 ptrdiff_t offset = cp - (char *) &b->floats[0];
4578 4549
4579 /* P must point to (or be a tagged pointer to) the start of a 4550 /* P must point to the start of a Lisp_Float and not be
4580 Lisp_Float and not be one of the unused cells in the current 4551 one of the unused cells in the current float block. */
4581 float block. */ 4552 return (0 <= offset && offset < sizeof b->floats
4582 if (0 <= offset && offset < sizeof b->floats) 4553 && offset % sizeof b->floats[0] == 0
4583 {
4584 int off = offset % sizeof b->floats[0];
4585 if ((off == Lisp_Float || off == 0)
4586 && (b != float_block 4554 && (b != float_block
4587 || offset / sizeof b->floats[0] < float_block_index)) 4555 || 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);
4631} 4556}
4632 4557
4633/* If P is a pointer to a live, large vector-like object, return the object. 4558/* If P is a pointer to a live, large vector-like object, return the object.
@@ -4638,7 +4563,10 @@ static struct Lisp_Vector *
4638live_large_vector_holding (struct mem_node *m, void *p) 4563live_large_vector_holding (struct mem_node *m, void *p)
4639{ 4564{
4640 eassert (m->type == MEM_TYPE_VECTORLIKE); 4565 eassert (m->type == MEM_TYPE_VECTORLIKE);
4641 return live_vector_pointer (large_vector_vec (m->start), p); 4566 struct Lisp_Vector *vp = 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;
4642} 4570}
4643 4571
4644static bool 4572static bool
@@ -4668,7 +4596,7 @@ live_small_vector_holding (struct mem_node *m, void *p)
4668 { 4596 {
4669 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector)); 4597 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
4670 if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE)) 4598 if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
4671 return live_vector_pointer (vector, vp); 4599 return vector;
4672 vector = next; 4600 vector = next;
4673 } 4601 }
4674 return NULL; 4602 return NULL;
@@ -4680,33 +4608,117 @@ live_small_vector_p (struct mem_node *m, void *p)
4680 return live_small_vector_holding (m, p) == p; 4608 return live_small_vector_holding (m, p) == p;
4681} 4609}
4682 4610
4683/* If P points to Lisp data, mark that as live if it isn't already 4611/* Mark OBJ if we can prove it's a Lisp_Object. */
4684 marked. */
4685 4612
4686static void 4613static void
4687mark_maybe_pointer (void *p) 4614mark_maybe_object (Lisp_Object obj)
4688{ 4615{
4689 struct mem_node *m;
4690
4691#if USE_VALGRIND 4616#if USE_VALGRIND
4692 VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p)); 4617 VALGRIND_MAKE_MEM_DEFINED (&obj, sizeof (obj));
4693#endif 4618#endif
4694 4619
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
4695 /* If the pointer is in the dump image and the dump has a record 4640 /* If the pointer is in the dump image and the dump has a record
4696 of the object starting at the place where the pointer points, we 4641 of the object starting at the place where the pointer points, we
4697 definitely have an object. If the pointer is in the dump image 4642 definitely have an object. If the pointer is in the dump image
4698 and the dump has no idea what the pointer is pointing at, we 4643 and the dump has no idea what the pointer is pointing at, we
4699 definitely _don't_ have an object. */ 4644 definitely _don't_ have an object. */
4700 if (pdumper_object_p (p)) 4645 if (pdumper_object_p (po))
4701 { 4646 {
4702 /* Don't use pdumper_object_p_precise here! It doesn't check the 4647 /* Don't use pdumper_object_p_precise here! It doesn't check the
4703 tag bits. OBJ here might be complete garbage, so we need to 4648 tag bits. OBJ here might be complete garbage, so we need to
4704 verify both the pointer and the tag. */ 4649 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 {
4705 int type = pdumper_find_object_type (p); 4716 int type = pdumper_find_object_type (p);
4706 if (pdumper_valid_object_type_p (type)) 4717 if (pdumper_valid_object_type_p (type))
4707 mark_object (type == Lisp_Symbol 4718 mark_object (type == Lisp_Symbol
4708 ? make_lisp_symbol (p) 4719 ? make_lisp_symbol (p)
4709 : make_lisp_ptr (p, type)); 4720 : make_lisp_ptr (p, type));
4721 /* See mark_maybe_object for why we can confidently return. */
4710 return; 4722 return;
4711 } 4723 }
4712 4724
@@ -4750,12 +4762,9 @@ mark_maybe_pointer (void *p)
4750 break; 4762 break;
4751 4763
4752 case MEM_TYPE_FLOAT: 4764 case MEM_TYPE_FLOAT:
4753 { 4765 if (! live_float_p (m, p))
4754 struct Lisp_Float *h = live_float_holding (m, p); 4766 return;
4755 if (!h) 4767 obj = make_lisp_ptr (p, Lisp_Float);
4756 return;
4757 obj = make_lisp_ptr (h, Lisp_Float);
4758 }
4759 break; 4768 break;
4760 4769
4761 case MEM_TYPE_VECTORLIKE: 4770 case MEM_TYPE_VECTORLIKE:
@@ -4840,6 +4849,11 @@ mark_memory (void const *start, void const *end)
4840 intptr_t ip; 4849 intptr_t ip;
4841 INT_ADD_WRAPV ((intptr_t) p, (intptr_t) lispsym, &ip); 4850 INT_ADD_WRAPV ((intptr_t) p, (intptr_t) lispsym, &ip);
4842 mark_maybe_pointer ((void *) ip); 4851 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);
4843 } 4857 }
4844} 4858}
4845 4859
@@ -6247,6 +6261,7 @@ mark_vectorlike (union vectorlike_header *header)
6247{ 6261{
6248 struct Lisp_Vector *ptr = (struct Lisp_Vector *) header; 6262 struct Lisp_Vector *ptr = (struct Lisp_Vector *) header;
6249 ptrdiff_t size = ptr->header.size; 6263 ptrdiff_t size = ptr->header.size;
6264 ptrdiff_t i;
6250 6265
6251 eassert (!vector_marked_p (ptr)); 6266 eassert (!vector_marked_p (ptr));
6252 6267
@@ -6261,7 +6276,8 @@ mark_vectorlike (union vectorlike_header *header)
6261 the number of Lisp_Object fields that we should trace. 6276 the number of Lisp_Object fields that we should trace.
6262 The distinction is used e.g. by Lisp_Process which places extra 6277 The distinction is used e.g. by Lisp_Process which places extra
6263 non-Lisp_Object fields at the end of the structure... */ 6278 non-Lisp_Object fields at the end of the structure... */
6264 mark_objects (ptr->contents, size); 6279 for (i = 0; i < size; i++) /* ...and then mark its elements. */
6280 mark_object (ptr->contents[i]);
6265} 6281}
6266 6282
6267/* Like mark_vectorlike but optimized for char-tables (and 6283/* Like mark_vectorlike but optimized for char-tables (and
@@ -6360,7 +6376,8 @@ mark_face_cache (struct face_cache *c)
6360{ 6376{
6361 if (c) 6377 if (c)
6362 { 6378 {
6363 for (int i = 0; i < c->used; i++) 6379 int i, j;
6380 for (i = 0; i < c->used; ++i)
6364 { 6381 {
6365 struct face *face = FACE_FROM_ID_OR_NULL (c->f, i); 6382 struct face *face = FACE_FROM_ID_OR_NULL (c->f, i);
6366 6383
@@ -6369,7 +6386,8 @@ mark_face_cache (struct face_cache *c)
6369 if (face->font && !vectorlike_marked_p (&face->font->header)) 6386 if (face->font && !vectorlike_marked_p (&face->font->header))
6370 mark_vectorlike (&face->font->header); 6387 mark_vectorlike (&face->font->header);
6371 6388
6372 mark_objects (face->lface, LFACE_VECTOR_SIZE); 6389 for (j = 0; j < LFACE_VECTOR_SIZE; ++j)
6390 mark_object (face->lface[j]);
6373 } 6391 }
6374 } 6392 }
6375 } 6393 }
@@ -6482,13 +6500,6 @@ mark_hash_table (struct Lisp_Vector *ptr)
6482 } 6500 }
6483} 6501}
6484 6502
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
6492/* Determine type of generic Lisp_Object and mark it accordingly. 6503/* Determine type of generic Lisp_Object and mark it accordingly.
6493 6504
6494 This function implements a straightforward depth-first marking 6505 This function implements a straightforward depth-first marking