diff options
| author | Andrea Corallo | 2020-09-06 08:07:30 +0200 |
|---|---|---|
| committer | Andrea Corallo | 2020-09-06 08:07:30 +0200 |
| commit | 805563346613af1f13ecd1bf96ffd8efe4816b47 (patch) | |
| tree | 568434f474dd247c732f096e9e3c6e23c493a1b7 /src/alloc.c | |
| parent | 67c53691560616598f746491347bd223480e6172 (diff) | |
| parent | 669b46e6a39bb5ba5d2ed14baebd585af6130ec9 (diff) | |
| download | emacs-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.c | 247 |
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 | ||
| 4562 | static bool | 4591 | static struct Lisp_Float * |
| 4563 | live_float_p (struct mem_node *m, void *p) | 4592 | live_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 | |||
| 4616 | static bool | ||
| 4617 | live_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 | |||
| 4624 | static struct Lisp_Vector * | ||
| 4625 | live_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 * | |||
| 4583 | live_large_vector_holding (struct mem_node *m, void *p) | 4658 | live_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 | ||
| 4592 | static bool | 4664 | static 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 | ||
| 4633 | static void | 4706 | static void |
| 4634 | mark_maybe_object (Lisp_Object obj) | 4707 | mark_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 | |||
| 4715 | void | ||
| 4716 | mark_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 | |||
| 4725 | static void | ||
| 4726 | mark_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 | ||
| 6505 | void | ||
| 6506 | mark_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 |