aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorAndrea Corallo2020-09-06 08:07:30 +0200
committerAndrea Corallo2020-09-06 08:07:30 +0200
commit805563346613af1f13ecd1bf96ffd8efe4816b47 (patch)
tree568434f474dd247c732f096e9e3c6e23c493a1b7 /src/alloc.c
parent67c53691560616598f746491347bd223480e6172 (diff)
parent669b46e6a39bb5ba5d2ed14baebd585af6130ec9 (diff)
downloademacs-805563346613af1f13ecd1bf96ffd8efe4816b47.tar.gz
emacs-805563346613af1f13ecd1bf96ffd8efe4816b47.zip
Merge remote-tracking branch 'savannah/master' into HEAD
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 738a35ce715..6701bf002b7 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -4477,9 +4477,17 @@ live_string_holding (struct mem_node *m, void *p)
4477 must not be on the free-list. */ 4477 must not be on the free-list. */
4478 if (0 <= offset && offset < sizeof b->strings) 4478 if (0 <= offset && offset < sizeof b->strings)
4479 { 4479 {
4480 struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0]; 4480 ptrdiff_t off = offset % sizeof b->strings[0];
4481 if (s->u.s.data) 4481 if (off == Lisp_String
4482 return s; 4482 || off == 0
4483 || off == offsetof (struct Lisp_String, u.s.size_byte)
4484 || off == offsetof (struct Lisp_String, u.s.intervals)
4485 || off == offsetof (struct Lisp_String, u.s.data))
4486 {
4487 struct Lisp_String *s = p = cp -= off;
4488 if (s->u.s.data)
4489 return s;
4490 }
4483 } 4491 }
4484 return NULL; 4492 return NULL;
4485} 4493}
@@ -4509,9 +4517,15 @@ live_cons_holding (struct mem_node *m, void *p)
4509 && (b != cons_block 4517 && (b != cons_block
4510 || offset / sizeof b->conses[0] < cons_block_index)) 4518 || offset / sizeof b->conses[0] < cons_block_index))
4511 { 4519 {
4512 struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0]; 4520 ptrdiff_t off = offset % sizeof b->conses[0];
4513 if (!deadp (s->u.s.car)) 4521 if (off == Lisp_Cons
4514 return s; 4522 || off == 0
4523 || off == offsetof (struct Lisp_Cons, u.s.u.cdr))
4524 {
4525 struct Lisp_Cons *s = p = cp -= off;
4526 if (!deadp (s->u.s.car))
4527 return s;
4528 }
4515 } 4529 }
4516 return NULL; 4530 return NULL;
4517} 4531}
@@ -4542,9 +4556,23 @@ live_symbol_holding (struct mem_node *m, void *p)
4542 && (b != symbol_block 4556 && (b != symbol_block
4543 || offset / sizeof b->symbols[0] < symbol_block_index)) 4557 || offset / sizeof b->symbols[0] < symbol_block_index))
4544 { 4558 {
4545 struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0]; 4559 ptrdiff_t off = offset % sizeof b->symbols[0];
4546 if (!deadp (s->u.s.function)) 4560 if (off == Lisp_Symbol
4547 return s; 4561
4562 /* Plain '|| off == 0' would run afoul of GCC 10.2
4563 -Wlogical-op, as Lisp_Symbol happens to be zero. */
4564 || (Lisp_Symbol != 0 && off == 0)
4565
4566 || off == offsetof (struct Lisp_Symbol, u.s.name)
4567 || off == offsetof (struct Lisp_Symbol, u.s.val)
4568 || off == offsetof (struct Lisp_Symbol, u.s.function)
4569 || off == offsetof (struct Lisp_Symbol, u.s.plist)
4570 || off == offsetof (struct Lisp_Symbol, u.s.next))
4571 {
4572 struct Lisp_Symbol *s = p = cp -= off;
4573 if (!deadp (s->u.s.function))
4574 return s;
4575 }
4548 } 4576 }
4549 return NULL; 4577 return NULL;
4550} 4578}
@@ -4556,23 +4584,70 @@ live_symbol_p (struct mem_node *m, void *p)
4556} 4584}
4557 4585
4558 4586
4559/* Return true if P is a pointer to a live Lisp float on 4587/* If P is a (possibly-tagged) pointer to a live Lisp_Float on the
4560 the heap. M is a pointer to the mem_block for P. */ 4588 heap, return the address of the Lisp_Float. Otherwise, return NULL.
4589 M is a pointer to the mem_block for P. */
4561 4590
4562static bool 4591static struct Lisp_Float *
4563live_float_p (struct mem_node *m, void *p) 4592live_float_holding (struct mem_node *m, void *p)
4564{ 4593{
4565 eassert (m->type == MEM_TYPE_FLOAT); 4594 eassert (m->type == MEM_TYPE_FLOAT);
4566 struct float_block *b = m->start; 4595 struct float_block *b = m->start;
4567 char *cp = p; 4596 char *cp = p;
4568 ptrdiff_t offset = cp - (char *) &b->floats[0]; 4597 ptrdiff_t offset = cp - (char *) &b->floats[0];
4569 4598
4570 /* P must point to the start of a Lisp_Float and not be 4599 /* P must point to (or be a tagged pointer to) the start of a
4571 one of the unused cells in the current float block. */ 4600 Lisp_Float and not be one of the unused cells in the current
4572 return (0 <= offset && offset < sizeof b->floats 4601 float block. */
4573 && offset % sizeof b->floats[0] == 0 4602 if (0 <= offset && offset < sizeof b->floats)
4603 {
4604 int off = offset % sizeof b->floats[0];
4605 if ((off == Lisp_Float || off == 0)
4574 && (b != float_block 4606 && (b != float_block
4575 || offset / sizeof b->floats[0] < float_block_index)); 4607 || offset / sizeof b->floats[0] < float_block_index))
4608 {
4609 p = cp - off;
4610 return p;
4611 }
4612 }
4613 return NULL;
4614}
4615
4616static bool
4617live_float_p (struct mem_node *m, void *p)
4618{
4619 return live_float_holding (m, p) == p;
4620}
4621
4622/* Return VECTOR if P points within it, NULL otherwise. */
4623
4624static struct Lisp_Vector *
4625live_vector_pointer (struct Lisp_Vector *vector, void *p)
4626{
4627 void *vvector = vector;
4628 char *cvector = vvector;
4629 char *cp = p;
4630 ptrdiff_t offset = cp - cvector;
4631 return ((offset == Lisp_Vectorlike
4632 || offset == 0
4633 || (sizeof vector->header <= offset
4634 && offset < vector_nbytes (vector)
4635 && (! (vector->header.size & PSEUDOVECTOR_FLAG)
4636 ? (offsetof (struct Lisp_Vector, contents) <= offset
4637 && (((offset - offsetof (struct Lisp_Vector, contents))
4638 % word_size)
4639 == 0))
4640 /* For non-bool-vector pseudovectors, treat any pointer
4641 past the header as valid since it's too much of a pain
4642 to write special-case code for every pseudovector. */
4643 : (! PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR)
4644 || offset == offsetof (struct Lisp_Bool_Vector, size)
4645 || (offsetof (struct Lisp_Bool_Vector, data) <= offset
4646 && (((offset
4647 - offsetof (struct Lisp_Bool_Vector, data))
4648 % sizeof (bits_word))
4649 == 0))))))
4650 ? vector : NULL);
4576} 4651}
4577 4652
4578/* If P is a pointer to a live, large vector-like object, return the object. 4653/* If P is a pointer to a live, large vector-like object, return the object.
@@ -4583,10 +4658,7 @@ static struct Lisp_Vector *
4583live_large_vector_holding (struct mem_node *m, void *p) 4658live_large_vector_holding (struct mem_node *m, void *p)
4584{ 4659{
4585 eassert (m->type == MEM_TYPE_VECTORLIKE); 4660 eassert (m->type == MEM_TYPE_VECTORLIKE);
4586 struct Lisp_Vector *vp = p; 4661 return live_vector_pointer (large_vector_vec (m->start), p);
4587 struct Lisp_Vector *vector = large_vector_vec (m->start);
4588 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
4589 return vector <= vp && vp < next ? vector : NULL;
4590} 4662}
4591 4663
4592static bool 4664static bool
@@ -4616,7 +4688,7 @@ live_small_vector_holding (struct mem_node *m, void *p)
4616 { 4688 {
4617 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector)); 4689 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
4618 if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE)) 4690 if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
4619 return vector; 4691 return live_vector_pointer (vector, vp);
4620 vector = next; 4692 vector = next;
4621 } 4693 }
4622 return NULL; 4694 return NULL;
@@ -4628,117 +4700,33 @@ live_small_vector_p (struct mem_node *m, void *p)
4628 return live_small_vector_holding (m, p) == p; 4700 return live_small_vector_holding (m, p) == p;
4629} 4701}
4630 4702
4631/* Mark OBJ if we can prove it's a Lisp_Object. */ 4703/* If P points to Lisp data, mark that as live if it isn't already
4704 marked. */
4632 4705
4633static void 4706static void
4634mark_maybe_object (Lisp_Object obj) 4707mark_maybe_pointer (void *p)
4635{ 4708{
4709 struct mem_node *m;
4710
4636#if USE_VALGRIND 4711#if USE_VALGRIND
4637 VALGRIND_MAKE_MEM_DEFINED (&obj, sizeof (obj)); 4712 VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p));
4638#endif 4713#endif
4639 4714
4640 int type_tag = XTYPE (obj);
4641 intptr_t pointer_word_tag = LISP_WORD_TAG (type_tag), offset, ipo;
4642
4643 switch (type_tag)
4644 {
4645 case_Lisp_Int: case Lisp_Type_Unused0:
4646 return;
4647
4648 case Lisp_Symbol:
4649 offset = (intptr_t) lispsym;
4650 break;
4651
4652 default:
4653 offset = 0;
4654 break;
4655 }
4656
4657 INT_ADD_WRAPV ((intptr_t) XLP (obj), offset - pointer_word_tag, &ipo);
4658 void *po = (void *) ipo;
4659
4660 /* If the pointer is in the dump image and the dump has a record 4715 /* If the pointer is in the dump image and the dump has a record
4661 of the object starting at the place where the pointer points, we 4716 of the object starting at the place where the pointer points, we
4662 definitely have an object. If the pointer is in the dump image 4717 definitely have an object. If the pointer is in the dump image
4663 and the dump has no idea what the pointer is pointing at, we 4718 and the dump has no idea what the pointer is pointing at, we
4664 definitely _don't_ have an object. */ 4719 definitely _don't_ have an object. */
4665 if (pdumper_object_p (po)) 4720 if (pdumper_object_p (p))
4666 { 4721 {
4667 /* Don't use pdumper_object_p_precise here! It doesn't check the 4722 /* Don't use pdumper_object_p_precise here! It doesn't check the
4668 tag bits. OBJ here might be complete garbage, so we need to 4723 tag bits. OBJ here might be complete garbage, so we need to
4669 verify both the pointer and the tag. */ 4724 verify both the pointer and the tag. */
4670 if (pdumper_find_object_type (po) == type_tag)
4671 mark_object (obj);
4672 return;
4673 }
4674
4675 struct mem_node *m = mem_find (po);
4676
4677 if (m != MEM_NIL)
4678 {
4679 bool mark_p = false;
4680
4681 switch (type_tag)
4682 {
4683 case Lisp_String:
4684 mark_p = m->type == MEM_TYPE_STRING && live_string_p (m, po);
4685 break;
4686
4687 case Lisp_Cons:
4688 mark_p = m->type == MEM_TYPE_CONS && live_cons_p (m, po);
4689 break;
4690
4691 case Lisp_Symbol:
4692 mark_p = m->type == MEM_TYPE_SYMBOL && live_symbol_p (m, po);
4693 break;
4694
4695 case Lisp_Float:
4696 mark_p = m->type == MEM_TYPE_FLOAT && live_float_p (m, po);
4697 break;
4698
4699 case Lisp_Vectorlike:
4700 mark_p = (m->type == MEM_TYPE_VECTOR_BLOCK
4701 ? live_small_vector_p (m, po)
4702 : (m->type == MEM_TYPE_VECTORLIKE
4703 && live_large_vector_p (m, po)));
4704 break;
4705
4706 default:
4707 eassume (false);
4708 }
4709
4710 if (mark_p)
4711 mark_object (obj);
4712 }
4713}
4714
4715void
4716mark_maybe_objects (Lisp_Object const *array, ptrdiff_t nelts)
4717{
4718 for (Lisp_Object const *lim = array + nelts; array < lim; array++)
4719 mark_maybe_object (*array);
4720}
4721
4722/* If P points to Lisp data, mark that as live if it isn't already
4723 marked. */
4724
4725static void
4726mark_maybe_pointer (void *p)
4727{
4728 struct mem_node *m;
4729
4730#if USE_VALGRIND
4731 VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p));
4732#endif
4733
4734 if (pdumper_object_p (p))
4735 {
4736 int type = pdumper_find_object_type (p); 4725 int type = pdumper_find_object_type (p);
4737 if (pdumper_valid_object_type_p (type)) 4726 if (pdumper_valid_object_type_p (type))
4738 mark_object (type == Lisp_Symbol 4727 mark_object (type == Lisp_Symbol
4739 ? make_lisp_symbol (p) 4728 ? make_lisp_symbol (p)
4740 : make_lisp_ptr (p, type)); 4729 : make_lisp_ptr (p, type));
4741 /* See mark_maybe_object for why we can confidently return. */
4742 return; 4730 return;
4743 } 4731 }
4744 4732
@@ -4782,9 +4770,12 @@ mark_maybe_pointer (void *p)
4782 break; 4770 break;
4783 4771
4784 case MEM_TYPE_FLOAT: 4772 case MEM_TYPE_FLOAT:
4785 if (! live_float_p (m, p)) 4773 {
4786 return; 4774 struct Lisp_Float *h = live_float_holding (m, p);
4787 obj = make_lisp_ptr (p, Lisp_Float); 4775 if (!h)
4776 return;
4777 obj = make_lisp_ptr (h, Lisp_Float);
4778 }
4788 break; 4779 break;
4789 4780
4790 case MEM_TYPE_VECTORLIKE: 4781 case MEM_TYPE_VECTORLIKE:
@@ -4869,11 +4860,6 @@ mark_memory (void const *start, void const *end)
4869 intptr_t ip; 4860 intptr_t ip;
4870 INT_ADD_WRAPV ((intptr_t) p, (intptr_t) lispsym, &ip); 4861 INT_ADD_WRAPV ((intptr_t) p, (intptr_t) lispsym, &ip);
4871 mark_maybe_pointer ((void *) ip); 4862 mark_maybe_pointer ((void *) ip);
4872
4873 verify (alignof (Lisp_Object) % GC_POINTER_ALIGNMENT == 0);
4874 if (alignof (Lisp_Object) == GC_POINTER_ALIGNMENT
4875 || (uintptr_t) pp % alignof (Lisp_Object) == 0)
4876 mark_maybe_object (*(Lisp_Object const *) pp);
4877 } 4863 }
4878} 4864}
4879 4865
@@ -6281,7 +6267,6 @@ mark_vectorlike (union vectorlike_header *header)
6281{ 6267{
6282 struct Lisp_Vector *ptr = (struct Lisp_Vector *) header; 6268 struct Lisp_Vector *ptr = (struct Lisp_Vector *) header;
6283 ptrdiff_t size = ptr->header.size; 6269 ptrdiff_t size = ptr->header.size;
6284 ptrdiff_t i;
6285 6270
6286 eassert (!vector_marked_p (ptr)); 6271 eassert (!vector_marked_p (ptr));
6287 6272
@@ -6296,8 +6281,7 @@ mark_vectorlike (union vectorlike_header *header)
6296 the number of Lisp_Object fields that we should trace. 6281 the number of Lisp_Object fields that we should trace.
6297 The distinction is used e.g. by Lisp_Process which places extra 6282 The distinction is used e.g. by Lisp_Process which places extra
6298 non-Lisp_Object fields at the end of the structure... */ 6283 non-Lisp_Object fields at the end of the structure... */
6299 for (i = 0; i < size; i++) /* ...and then mark its elements. */ 6284 mark_objects (ptr->contents, size);
6300 mark_object (ptr->contents[i]);
6301} 6285}
6302 6286
6303/* Like mark_vectorlike but optimized for char-tables (and 6287/* Like mark_vectorlike but optimized for char-tables (and
@@ -6396,8 +6380,7 @@ mark_face_cache (struct face_cache *c)
6396{ 6380{
6397 if (c) 6381 if (c)
6398 { 6382 {
6399 int i, j; 6383 for (int i = 0; i < c->used; i++)
6400 for (i = 0; i < c->used; ++i)
6401 { 6384 {
6402 struct face *face = FACE_FROM_ID_OR_NULL (c->f, i); 6385 struct face *face = FACE_FROM_ID_OR_NULL (c->f, i);
6403 6386
@@ -6406,8 +6389,7 @@ mark_face_cache (struct face_cache *c)
6406 if (face->font && !vectorlike_marked_p (&face->font->header)) 6389 if (face->font && !vectorlike_marked_p (&face->font->header))
6407 mark_vectorlike (&face->font->header); 6390 mark_vectorlike (&face->font->header);
6408 6391
6409 for (j = 0; j < LFACE_VECTOR_SIZE; ++j) 6392 mark_objects (face->lface, LFACE_VECTOR_SIZE);
6410 mark_object (face->lface[j]);
6411 } 6393 }
6412 } 6394 }
6413 } 6395 }
@@ -6520,6 +6502,13 @@ mark_hash_table (struct Lisp_Vector *ptr)
6520 } 6502 }
6521} 6503}
6522 6504
6505void
6506mark_objects (Lisp_Object *obj, ptrdiff_t n)
6507{
6508 for (ptrdiff_t i = 0; i < n; i++)
6509 mark_object (obj[i]);
6510}
6511
6523/* Determine type of generic Lisp_Object and mark it accordingly. 6512/* Determine type of generic Lisp_Object and mark it accordingly.
6524 6513
6525 This function implements a straightforward depth-first marking 6514 This function implements a straightforward depth-first marking