aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2020-06-04 18:46:11 -0700
committerPaul Eggert2020-06-04 22:08:43 -0700
commit8ee367fe864d131a9d7f87677b9418ac78c922fa (patch)
tree2d2ed797873e5e68f50bd824be66d9d25a3f51ea
parent4dcf8f2205fcfb45b460a2256569e64a03f93b4a (diff)
downloademacs-8ee367fe864d131a9d7f87677b9418ac78c922fa.tar.gz
emacs-8ee367fe864d131a9d7f87677b9418ac78c922fa.zip
Streamline live_*_holding
(live_string_holding, live_cons_holding, live_symbol_holding) (live_float_p, live_vector_holding): Assert that m->type is correct, instead of testing this at runtime. All callers changed. (live_large_vector_holding, live_small_vector_holding): Now two functions instead of the old live_vector_holding. All callers changed. (live_large_vector_p, live_small_vector_p): Now two functions instead of the old live_vector_p. All callers changed. (mark_maybe_object): Ignore Lisp_Type_Unused0 quickly too, since that cannot possibly be an object. (CHECK_LIVE, CHECK_ALLOCATED_AND_LIVE): New arg MEM_TYPE. All callers changed. (CHECK_ALLOCATED_AND_LIVE_SYMBOL): Simplify by combining GC_CHECK_MARKED_OBJECTS code.
-rw-r--r--src/alloc.c272
1 files changed, 148 insertions, 124 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 5cb754d237b..ed30c449785 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -4449,21 +4449,19 @@ mem_delete_fixup (struct mem_node *x)
4449static struct Lisp_String * 4449static struct Lisp_String *
4450live_string_holding (struct mem_node *m, void *p) 4450live_string_holding (struct mem_node *m, void *p)
4451{ 4451{
4452 if (m->type == MEM_TYPE_STRING) 4452 eassert (m->type == MEM_TYPE_STRING);
4453 struct string_block *b = m->start;
4454 char *cp = p;
4455 ptrdiff_t offset = cp - (char *) &b->strings[0];
4456
4457 /* P must point into a Lisp_String structure, and it
4458 must not be on the free-list. */
4459 if (0 <= offset && offset < sizeof b->strings)
4453 { 4460 {
4454 struct string_block *b = m->start; 4461 cp = ptr_bounds_copy (cp, b);
4455 char *cp = p; 4462 struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0];
4456 ptrdiff_t offset = cp - (char *) &b->strings[0]; 4463 if (s->u.s.data)
4457 4464 return s;
4458 /* P must point into a Lisp_String structure, and it
4459 must not be on the free-list. */
4460 if (0 <= offset && offset < sizeof b->strings)
4461 {
4462 cp = ptr_bounds_copy (cp, b);
4463 struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0];
4464 if (s->u.s.data)
4465 return s;
4466 }
4467 } 4465 }
4468 return NULL; 4466 return NULL;
4469} 4467}
@@ -4481,24 +4479,22 @@ live_string_p (struct mem_node *m, void *p)
4481static struct Lisp_Cons * 4479static struct Lisp_Cons *
4482live_cons_holding (struct mem_node *m, void *p) 4480live_cons_holding (struct mem_node *m, void *p)
4483{ 4481{
4484 if (m->type == MEM_TYPE_CONS) 4482 eassert (m->type == MEM_TYPE_CONS);
4483 struct cons_block *b = m->start;
4484 char *cp = p;
4485 ptrdiff_t offset = cp - (char *) &b->conses[0];
4486
4487 /* P must point into a Lisp_Cons, not be
4488 one of the unused cells in the current cons block,
4489 and not be on the free-list. */
4490 if (0 <= offset && offset < sizeof b->conses
4491 && (b != cons_block
4492 || offset / sizeof b->conses[0] < cons_block_index))
4485 { 4493 {
4486 struct cons_block *b = m->start; 4494 cp = ptr_bounds_copy (cp, b);
4487 char *cp = p; 4495 struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0];
4488 ptrdiff_t offset = cp - (char *) &b->conses[0]; 4496 if (!deadp (s->u.s.car))
4489 4497 return s;
4490 /* P must point into a Lisp_Cons, not be
4491 one of the unused cells in the current cons block,
4492 and not be on the free-list. */
4493 if (0 <= offset && offset < sizeof b->conses
4494 && (b != cons_block
4495 || offset / sizeof b->conses[0] < cons_block_index))
4496 {
4497 cp = ptr_bounds_copy (cp, b);
4498 struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0];
4499 if (!deadp (s->u.s.car))
4500 return s;
4501 }
4502 } 4498 }
4503 return NULL; 4499 return NULL;
4504} 4500}
@@ -4517,24 +4513,22 @@ live_cons_p (struct mem_node *m, void *p)
4517static struct Lisp_Symbol * 4513static struct Lisp_Symbol *
4518live_symbol_holding (struct mem_node *m, void *p) 4514live_symbol_holding (struct mem_node *m, void *p)
4519{ 4515{
4520 if (m->type == MEM_TYPE_SYMBOL) 4516 eassert (m->type == MEM_TYPE_SYMBOL);
4517 struct symbol_block *b = m->start;
4518 char *cp = p;
4519 ptrdiff_t offset = cp - (char *) &b->symbols[0];
4520
4521 /* P must point into the Lisp_Symbol, not be
4522 one of the unused cells in the current symbol block,
4523 and not be on the free-list. */
4524 if (0 <= offset && offset < sizeof b->symbols
4525 && (b != symbol_block
4526 || offset / sizeof b->symbols[0] < symbol_block_index))
4521 { 4527 {
4522 struct symbol_block *b = m->start; 4528 cp = ptr_bounds_copy (cp, b);
4523 char *cp = p; 4529 struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0];
4524 ptrdiff_t offset = cp - (char *) &b->symbols[0]; 4530 if (!deadp (s->u.s.function))
4525 4531 return s;
4526 /* P must point into the Lisp_Symbol, not be
4527 one of the unused cells in the current symbol block,
4528 and not be on the free-list. */
4529 if (0 <= offset && offset < sizeof b->symbols
4530 && (b != symbol_block
4531 || offset / sizeof b->symbols[0] < symbol_block_index))
4532 {
4533 cp = ptr_bounds_copy (cp, b);
4534 struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0];
4535 if (!deadp (s->u.s.function))
4536 return s;
4537 }
4538 } 4532 }
4539 return NULL; 4533 return NULL;
4540} 4534}
@@ -4552,66 +4546,70 @@ live_symbol_p (struct mem_node *m, void *p)
4552static bool 4546static bool
4553live_float_p (struct mem_node *m, void *p) 4547live_float_p (struct mem_node *m, void *p)
4554{ 4548{
4555 if (m->type == MEM_TYPE_FLOAT) 4549 eassert (m->type == MEM_TYPE_FLOAT);
4556 { 4550 struct float_block *b = m->start;
4557 struct float_block *b = m->start; 4551 char *cp = p;
4558 char *cp = p; 4552 ptrdiff_t offset = cp - (char *) &b->floats[0];
4559 ptrdiff_t offset = cp - (char *) &b->floats[0]; 4553
4560 4554 /* P must point to the start of a Lisp_Float and not be
4561 /* P must point to the start of a Lisp_Float and not be 4555 one of the unused cells in the current float block. */
4562 one of the unused cells in the current float block. */ 4556 return (0 <= offset && offset < sizeof b->floats
4563 return (0 <= offset && offset < sizeof b->floats 4557 && offset % sizeof b->floats[0] == 0
4564 && offset % sizeof b->floats[0] == 0 4558 && (b != float_block
4565 && (b != float_block 4559 || offset / sizeof b->floats[0] < float_block_index));
4566 || offset / sizeof b->floats[0] < float_block_index));
4567 }
4568 else
4569 return 0;
4570} 4560}
4571 4561
4572/* If P is a pointer to a live vector-like object, return the object. 4562/* If P is a pointer to a live, large vector-like object, return the object.
4573 Otherwise, return nil. 4563 Otherwise, return nil.
4574 M is a pointer to the mem_block for P. */ 4564 M is a pointer to the mem_block for P. */
4575 4565
4576static struct Lisp_Vector * 4566static struct Lisp_Vector *
4577live_vector_holding (struct mem_node *m, void *p) 4567live_large_vector_holding (struct mem_node *m, void *p)
4578{ 4568{
4569 eassert (m->type == MEM_TYPE_VECTORLIKE);
4579 struct Lisp_Vector *vp = p; 4570 struct Lisp_Vector *vp = p;
4571 struct Lisp_Vector *vector = large_vector_vec (m->start);
4572 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
4573 return vector <= vp && vp < next ? vector : NULL;
4574}
4580 4575
4581 if (m->type == MEM_TYPE_VECTOR_BLOCK) 4576static bool
4582 { 4577live_large_vector_p (struct mem_node *m, void *p)
4583 /* This memory node corresponds to a vector block. */ 4578{
4584 struct vector_block *block = m->start; 4579 return live_large_vector_holding (m, p) == p;
4585 struct Lisp_Vector *vector = (struct Lisp_Vector *) block->data; 4580}
4586 4581
4587 /* P is in the block's allocation range. Scan the block 4582/* If P is a pointer to a live, small vector-like object, return the object.
4588 up to P and see whether P points to the start of some 4583 Otherwise, return NULL.
4589 vector which is not on a free list. FIXME: check whether 4584 M is a pointer to the mem_block for P. */
4590 some allocation patterns (probably a lot of short vectors) 4585
4591 may cause a substantial overhead of this loop. */ 4586static struct Lisp_Vector *
4592 while (VECTOR_IN_BLOCK (vector, block) && vector <= vp) 4587live_small_vector_holding (struct mem_node *m, void *p)
4593 { 4588{
4594 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector)); 4589 eassert (m->type == MEM_TYPE_VECTOR_BLOCK);
4595 if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE)) 4590 struct Lisp_Vector *vp = p;
4596 return vector; 4591 struct vector_block *block = m->start;
4597 vector = next; 4592 struct Lisp_Vector *vector = (struct Lisp_Vector *) block->data;
4598 } 4593
4599 } 4594 /* P is in the block's allocation range. Scan the block
4600 else if (m->type == MEM_TYPE_VECTORLIKE) 4595 up to P and see whether P points to the start of some
4596 vector which is not on a free list. FIXME: check whether
4597 some allocation patterns (probably a lot of short vectors)
4598 may cause a substantial overhead of this loop. */
4599 while (VECTOR_IN_BLOCK (vector, block) && vector <= vp)
4601 { 4600 {
4602 /* This memory node corresponds to a large vector. */
4603 struct Lisp_Vector *vector = large_vector_vec (m->start);
4604 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector)); 4601 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
4605 if (vector <= vp && vp < next) 4602 if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
4606 return vector; 4603 return vector;
4604 vector = next;
4607 } 4605 }
4608 return NULL; 4606 return NULL;
4609} 4607}
4610 4608
4611static bool 4609static bool
4612live_vector_p (struct mem_node *m, void *p) 4610live_small_vector_p (struct mem_node *m, void *p)
4613{ 4611{
4614 return live_vector_holding (m, p) == p; 4612 return live_small_vector_holding (m, p) == p;
4615} 4613}
4616 4614
4617/* Mark OBJ if we can prove it's a Lisp_Object. */ 4615/* Mark OBJ if we can prove it's a Lisp_Object. */
@@ -4623,10 +4621,24 @@ mark_maybe_object (Lisp_Object obj)
4623 VALGRIND_MAKE_MEM_DEFINED (&obj, sizeof (obj)); 4621 VALGRIND_MAKE_MEM_DEFINED (&obj, sizeof (obj));
4624#endif 4622#endif
4625 4623
4626 if (FIXNUMP (obj)) 4624 int type_tag = XTYPE (obj);
4627 return; 4625 intptr_t offset;
4628 4626
4629 void *po = XPNTR (obj); 4627 switch (type_tag)
4628 {
4629 case_Lisp_Int: case Lisp_Type_Unused0:
4630 return;
4631
4632 case Lisp_Symbol:
4633 offset = (intptr_t) lispsym;
4634 break;
4635
4636 default:
4637 offset = 0;
4638 break;
4639 }
4640
4641 void *po = (char *) XLP (obj) + (offset - LISP_WORD_TAG (type_tag));
4630 4642
4631 /* If the pointer is in the dump image and the dump has a record 4643 /* If the pointer is in the dump image and the dump has a record
4632 of the object starting at the place where the pointer points, we 4644 of the object starting at the place where the pointer points, we
@@ -4638,7 +4650,7 @@ mark_maybe_object (Lisp_Object obj)
4638 /* Don't use pdumper_object_p_precise here! It doesn't check the 4650 /* Don't use pdumper_object_p_precise here! It doesn't check the
4639 tag bits. OBJ here might be complete garbage, so we need to 4651 tag bits. OBJ here might be complete garbage, so we need to
4640 verify both the pointer and the tag. */ 4652 verify both the pointer and the tag. */
4641 if (XTYPE (obj) == pdumper_find_object_type (po)) 4653 if (pdumper_find_object_type (po) == type_tag)
4642 mark_object (obj); 4654 mark_object (obj);
4643 return; 4655 return;
4644 } 4656 }
@@ -4649,30 +4661,33 @@ mark_maybe_object (Lisp_Object obj)
4649 { 4661 {
4650 bool mark_p = false; 4662 bool mark_p = false;
4651 4663
4652 switch (XTYPE (obj)) 4664 switch (type_tag)
4653 { 4665 {
4654 case Lisp_String: 4666 case Lisp_String:
4655 mark_p = live_string_p (m, po); 4667 mark_p = m->type == MEM_TYPE_STRING && live_string_p (m, po);
4656 break; 4668 break;
4657 4669
4658 case Lisp_Cons: 4670 case Lisp_Cons:
4659 mark_p = live_cons_p (m, po); 4671 mark_p = m->type == MEM_TYPE_CONS && live_cons_p (m, po);
4660 break; 4672 break;
4661 4673
4662 case Lisp_Symbol: 4674 case Lisp_Symbol:
4663 mark_p = live_symbol_p (m, po); 4675 mark_p = m->type == MEM_TYPE_SYMBOL && live_symbol_p (m, po);
4664 break; 4676 break;
4665 4677
4666 case Lisp_Float: 4678 case Lisp_Float:
4667 mark_p = live_float_p (m, po); 4679 mark_p = m->type == MEM_TYPE_FLOAT && live_float_p (m, po);
4668 break; 4680 break;
4669 4681
4670 case Lisp_Vectorlike: 4682 case Lisp_Vectorlike:
4671 mark_p = live_vector_p (m, po); 4683 mark_p = (m->type == MEM_TYPE_VECTOR_BLOCK
4684 ? live_small_vector_p (m, po)
4685 : (m->type == MEM_TYPE_VECTORLIKE
4686 && live_large_vector_p (m, po)));
4672 break; 4687 break;
4673 4688
4674 default: 4689 default:
4675 break; 4690 eassume (false);
4676 } 4691 }
4677 4692
4678 if (mark_p) 4693 if (mark_p)
@@ -4756,9 +4771,17 @@ mark_maybe_pointer (void *p)
4756 break; 4771 break;
4757 4772
4758 case MEM_TYPE_VECTORLIKE: 4773 case MEM_TYPE_VECTORLIKE:
4774 {
4775 struct Lisp_Vector *h = live_large_vector_holding (m, p);
4776 if (!h)
4777 return;
4778 obj = make_lisp_ptr (h, Lisp_Vectorlike);
4779 }
4780 break;
4781
4759 case MEM_TYPE_VECTOR_BLOCK: 4782 case MEM_TYPE_VECTOR_BLOCK:
4760 { 4783 {
4761 struct Lisp_Vector *h = live_vector_holding (m, p); 4784 struct Lisp_Vector *h = live_small_vector_holding (m, p);
4762 if (!h) 4785 if (!h)
4763 return; 4786 return;
4764 obj = make_lisp_ptr (h, Lisp_Vectorlike); 4787 obj = make_lisp_ptr (h, Lisp_Vectorlike);
@@ -5176,8 +5199,10 @@ valid_lisp_object_p (Lisp_Object obj)
5176 return live_float_p (m, p); 5199 return live_float_p (m, p);
5177 5200
5178 case MEM_TYPE_VECTORLIKE: 5201 case MEM_TYPE_VECTORLIKE:
5202 return live_large_vector_p (m, p);
5203
5179 case MEM_TYPE_VECTOR_BLOCK: 5204 case MEM_TYPE_VECTOR_BLOCK:
5180 return live_vector_p (m, p); 5205 return live_small_vector_p (m, p);
5181 5206
5182 default: 5207 default:
5183 break; 5208 break;
@@ -6551,19 +6576,19 @@ mark_object (Lisp_Object arg)
6551 6576
6552 /* Check that the object pointed to by PO is live, using predicate 6577 /* Check that the object pointed to by PO is live, using predicate
6553 function LIVEP. */ 6578 function LIVEP. */
6554#define CHECK_LIVE(LIVEP) \ 6579#define CHECK_LIVE(LIVEP, MEM_TYPE) \
6555 do { \ 6580 do { \
6556 if (pdumper_object_p (po)) \ 6581 if (pdumper_object_p (po)) \
6557 break; \ 6582 break; \
6558 if (!LIVEP (m, po)) \ 6583 if (! (m->type == MEM_TYPE && LIVEP (m, po))) \
6559 emacs_abort (); \ 6584 emacs_abort (); \
6560 } while (0) 6585 } while (0)
6561 6586
6562 /* Check both of the above conditions, for non-symbols. */ 6587 /* Check both of the above conditions, for non-symbols. */
6563#define CHECK_ALLOCATED_AND_LIVE(LIVEP) \ 6588#define CHECK_ALLOCATED_AND_LIVE(LIVEP, MEM_TYPE) \
6564 do { \ 6589 do { \
6565 CHECK_ALLOCATED (); \ 6590 CHECK_ALLOCATED (); \
6566 CHECK_LIVE (LIVEP); \ 6591 CHECK_LIVE (LIVEP, MEM_TYPE); \
6567 } while (false) 6592 } while (false)
6568 6593
6569 /* Check both of the above conditions, for symbols. */ 6594 /* Check both of the above conditions, for symbols. */
@@ -6572,15 +6597,14 @@ mark_object (Lisp_Object arg)
6572 if (!c_symbol_p (ptr)) \ 6597 if (!c_symbol_p (ptr)) \
6573 { \ 6598 { \
6574 CHECK_ALLOCATED (); \ 6599 CHECK_ALLOCATED (); \
6575 CHECK_LIVE (live_symbol_p); \ 6600 CHECK_LIVE (live_symbol_p, MEM_TYPE_SYMBOL); \
6576 } \ 6601 } \
6577 } while (false) 6602 } while (false)
6578 6603
6579#else /* not GC_CHECK_MARKED_OBJECTS */ 6604#else /* not GC_CHECK_MARKED_OBJECTS */
6580 6605
6581#define CHECK_LIVE(LIVEP) ((void) 0) 6606#define CHECK_ALLOCATED_AND_LIVE(LIVEP, MEM_TYPE) ((void) 0)
6582#define CHECK_ALLOCATED_AND_LIVE(LIVEP) ((void) 0) 6607#define CHECK_ALLOCATED_AND_LIVE_SYMBOL() ((void) 0)
6583#define CHECK_ALLOCATED_AND_LIVE_SYMBOL() ((void) 0)
6584 6608
6585#endif /* not GC_CHECK_MARKED_OBJECTS */ 6609#endif /* not GC_CHECK_MARKED_OBJECTS */
6586 6610
@@ -6591,7 +6615,7 @@ mark_object (Lisp_Object arg)
6591 register struct Lisp_String *ptr = XSTRING (obj); 6615 register struct Lisp_String *ptr = XSTRING (obj);
6592 if (string_marked_p (ptr)) 6616 if (string_marked_p (ptr))
6593 break; 6617 break;
6594 CHECK_ALLOCATED_AND_LIVE (live_string_p); 6618 CHECK_ALLOCATED_AND_LIVE (live_string_p, MEM_TYPE_STRING);
6595 set_string_marked (ptr); 6619 set_string_marked (ptr);
6596 mark_interval_tree (ptr->u.s.intervals); 6620 mark_interval_tree (ptr->u.s.intervals);
6597#ifdef GC_CHECK_STRING_BYTES 6621#ifdef GC_CHECK_STRING_BYTES
@@ -6609,21 +6633,21 @@ mark_object (Lisp_Object arg)
6609 if (vector_marked_p (ptr)) 6633 if (vector_marked_p (ptr))
6610 break; 6634 break;
6611 6635
6636 enum pvec_type pvectype
6637 = PSEUDOVECTOR_TYPE (ptr);
6638
6612#ifdef GC_CHECK_MARKED_OBJECTS 6639#ifdef GC_CHECK_MARKED_OBJECTS
6613 if (!pdumper_object_p (po)) 6640 if (!pdumper_object_p (po) && !SUBRP (obj) && !main_thread_p (po))
6614 { 6641 {
6615 m = mem_find (po); 6642 m = mem_find (po);
6616 if (m == MEM_NIL && !SUBRP (obj) && !main_thread_p (po)) 6643 if (m == MEM_NIL)
6617 emacs_abort (); 6644 emacs_abort ();
6645 if (m->type == MEM_TYPE_VECTORLIKE)
6646 CHECK_LIVE (live_large_vector_p, MEM_TYPE_VECTORLIKE);
6647 else
6648 CHECK_LIVE (live_small_vector_p, MEM_TYPE_VECTOR_BLOCK);
6618 } 6649 }
6619#endif /* GC_CHECK_MARKED_OBJECTS */ 6650#endif
6620
6621 enum pvec_type pvectype
6622 = PSEUDOVECTOR_TYPE (ptr);
6623
6624 if (pvectype != PVEC_SUBR &&
6625 !main_thread_p (po))
6626 CHECK_LIVE (live_vector_p);
6627 6651
6628 switch (pvectype) 6652 switch (pvectype)
6629 { 6653 {
@@ -6734,7 +6758,7 @@ mark_object (Lisp_Object arg)
6734 struct Lisp_Cons *ptr = XCONS (obj); 6758 struct Lisp_Cons *ptr = XCONS (obj);
6735 if (cons_marked_p (ptr)) 6759 if (cons_marked_p (ptr))
6736 break; 6760 break;
6737 CHECK_ALLOCATED_AND_LIVE (live_cons_p); 6761 CHECK_ALLOCATED_AND_LIVE (live_cons_p, MEM_TYPE_CONS);
6738 set_cons_marked (ptr); 6762 set_cons_marked (ptr);
6739 /* If the cdr is nil, avoid recursion for the car. */ 6763 /* If the cdr is nil, avoid recursion for the car. */
6740 if (NILP (ptr->u.s.u.cdr)) 6764 if (NILP (ptr->u.s.u.cdr))
@@ -6752,7 +6776,7 @@ mark_object (Lisp_Object arg)
6752 } 6776 }
6753 6777
6754 case Lisp_Float: 6778 case Lisp_Float:
6755 CHECK_ALLOCATED_AND_LIVE (live_float_p); 6779 CHECK_ALLOCATED_AND_LIVE (live_float_p, MEM_TYPE_FLOAT);
6756 /* Do not mark floats stored in a dump image: these floats are 6780 /* Do not mark floats stored in a dump image: these floats are
6757 "cold" and do not have mark bits. */ 6781 "cold" and do not have mark bits. */
6758 if (pdumper_object_p (XFLOAT (obj))) 6782 if (pdumper_object_p (XFLOAT (obj)))