diff options
| author | Paul Eggert | 2015-06-24 20:10:03 -0700 |
|---|---|---|
| committer | Paul Eggert | 2015-06-24 20:10:44 -0700 |
| commit | 93f4f67ba93b78e8b31e498e8ce7bce4c8298b76 (patch) | |
| tree | 788c0808926664ea23de2f903f4c233c5febf7ab /src | |
| parent | f230b2ff3136120a9be544a5d3a974f7087ce55b (diff) | |
| download | emacs-93f4f67ba93b78e8b31e498e8ce7bce4c8298b76.tar.gz emacs-93f4f67ba93b78e8b31e498e8ce7bce4c8298b76.zip | |
Fix GC bugs --with-wide-int and Qnil == 0
Use the same alignment for the !USE_LSB_TAG case as for the
more-typical USE_LSB_TAG case. The attempt to support arbitrary
alignments with !USE_LSB_TAG had subtle bugs in garbage collection
once we changed the representation of symbols so that Qnil == 0.
Problem reported by Eli Zaretskii (Bug#20862).
* src/alloc.c (XMALLOC_HEADER_ALIGNMENT) [XMALLOC_OVERRUN_CHECK]:
* src/alloc.c (vector_alignment, union aligned_Lisp_Symbol)
(union aligned_Lisp_Misc, maybe_lisp_pointer, pure_alloc):
Use same alignment for !USE_LSB_TAG as for USE_LSB_TAG.
* src/alloc.c (POINTERS_MIGHT_HIDE_IN_OBJECTS): Remove.
This optimization in the !USE_LSB_TAG case is no longer valid when
symbols are represented via offsets. Change the only use to
assume that pointers might hide in objects.
* src/lisp.h (alignas) [!USE_LSB_TAG]:
Require support in this case, too.
(TAG_SYMOFFSET, XSYMBOL) [!USE_LSB_TAG]: Do not shift the offset.
This is OK, because the !USE_LSB_TAG case now applies only when
Lisp_Object is wider than void *, so there's no longer any need
to shift the offset. Not shifting the offset means that
symbol representations have the same alignment as pointers,
which the GC assumes.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 59 | ||||
| -rw-r--r-- | src/lisp.h | 11 |
2 files changed, 12 insertions, 58 deletions
diff --git a/src/alloc.c b/src/alloc.c index a956e95bf14..c9bdcc216c7 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -528,12 +528,8 @@ buffer_memory_full (ptrdiff_t nbytes) | |||
| 528 | alignment that Emacs needs for C types and for USE_LSB_TAG. */ | 528 | alignment that Emacs needs for C types and for USE_LSB_TAG. */ |
| 529 | #define XMALLOC_BASE_ALIGNMENT alignof (max_align_t) | 529 | #define XMALLOC_BASE_ALIGNMENT alignof (max_align_t) |
| 530 | 530 | ||
| 531 | #if USE_LSB_TAG | 531 | #define XMALLOC_HEADER_ALIGNMENT \ |
| 532 | # define XMALLOC_HEADER_ALIGNMENT \ | 532 | COMMON_MULTIPLE (GCALIGNMENT, XMALLOC_BASE_ALIGNMENT) |
| 533 | COMMON_MULTIPLE (GCALIGNMENT, XMALLOC_BASE_ALIGNMENT) | ||
| 534 | #else | ||
| 535 | # define XMALLOC_HEADER_ALIGNMENT XMALLOC_BASE_ALIGNMENT | ||
| 536 | #endif | ||
| 537 | #define XMALLOC_OVERRUN_SIZE_SIZE \ | 533 | #define XMALLOC_OVERRUN_SIZE_SIZE \ |
| 538 | (((XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t) \ | 534 | (((XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t) \ |
| 539 | + XMALLOC_HEADER_ALIGNMENT - 1) \ | 535 | + XMALLOC_HEADER_ALIGNMENT - 1) \ |
| @@ -2730,7 +2726,7 @@ enum | |||
| 2730 | { | 2726 | { |
| 2731 | /* Alignment of struct Lisp_Vector objects. */ | 2727 | /* Alignment of struct Lisp_Vector objects. */ |
| 2732 | vector_alignment = COMMON_MULTIPLE (ALIGNOF_STRUCT_LISP_VECTOR, | 2728 | vector_alignment = COMMON_MULTIPLE (ALIGNOF_STRUCT_LISP_VECTOR, |
| 2733 | USE_LSB_TAG ? GCALIGNMENT : 1), | 2729 | GCALIGNMENT), |
| 2734 | 2730 | ||
| 2735 | /* Vector size requests are a multiple of this. */ | 2731 | /* Vector size requests are a multiple of this. */ |
| 2736 | roundup_size = COMMON_MULTIPLE (vector_alignment, word_size) | 2732 | roundup_size = COMMON_MULTIPLE (vector_alignment, word_size) |
| @@ -3299,15 +3295,13 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT | |||
| 3299 | ***********************************************************************/ | 3295 | ***********************************************************************/ |
| 3300 | 3296 | ||
| 3301 | /* Like struct Lisp_Symbol, but padded so that the size is a multiple | 3297 | /* Like struct Lisp_Symbol, but padded so that the size is a multiple |
| 3302 | of the required alignment if LSB tags are used. */ | 3298 | of the required alignment. */ |
| 3303 | 3299 | ||
| 3304 | union aligned_Lisp_Symbol | 3300 | union aligned_Lisp_Symbol |
| 3305 | { | 3301 | { |
| 3306 | struct Lisp_Symbol s; | 3302 | struct Lisp_Symbol s; |
| 3307 | #if USE_LSB_TAG | ||
| 3308 | unsigned char c[(sizeof (struct Lisp_Symbol) + GCALIGNMENT - 1) | 3303 | unsigned char c[(sizeof (struct Lisp_Symbol) + GCALIGNMENT - 1) |
| 3309 | & -GCALIGNMENT]; | 3304 | & -GCALIGNMENT]; |
| 3310 | #endif | ||
| 3311 | }; | 3305 | }; |
| 3312 | 3306 | ||
| 3313 | /* Each symbol_block is just under 1020 bytes long, since malloc | 3307 | /* Each symbol_block is just under 1020 bytes long, since malloc |
| @@ -3411,15 +3405,13 @@ Its value is void, and its function definition and property list are nil. */) | |||
| 3411 | ***********************************************************************/ | 3405 | ***********************************************************************/ |
| 3412 | 3406 | ||
| 3413 | /* Like union Lisp_Misc, but padded so that its size is a multiple of | 3407 | /* Like union Lisp_Misc, but padded so that its size is a multiple of |
| 3414 | the required alignment when LSB tags are used. */ | 3408 | the required alignment. */ |
| 3415 | 3409 | ||
| 3416 | union aligned_Lisp_Misc | 3410 | union aligned_Lisp_Misc |
| 3417 | { | 3411 | { |
| 3418 | union Lisp_Misc m; | 3412 | union Lisp_Misc m; |
| 3419 | #if USE_LSB_TAG | ||
| 3420 | unsigned char c[(sizeof (union Lisp_Misc) + GCALIGNMENT - 1) | 3413 | unsigned char c[(sizeof (union Lisp_Misc) + GCALIGNMENT - 1) |
| 3421 | & -GCALIGNMENT]; | 3414 | & -GCALIGNMENT]; |
| 3422 | #endif | ||
| 3423 | }; | 3415 | }; |
| 3424 | 3416 | ||
| 3425 | /* Allocation of markers and other objects that share that structure. | 3417 | /* Allocation of markers and other objects that share that structure. |
| @@ -4628,13 +4620,13 @@ mark_maybe_object (Lisp_Object obj) | |||
| 4628 | } | 4620 | } |
| 4629 | 4621 | ||
| 4630 | /* Return true if P can point to Lisp data, and false otherwise. | 4622 | /* Return true if P can point to Lisp data, and false otherwise. |
| 4631 | USE_LSB_TAG needs Lisp data to be aligned on multiples of GCALIGNMENT. | 4623 | Symbols are implemented via offsets not pointers, but the offsets |
| 4632 | Otherwise, assume that Lisp data is aligned on even addresses. */ | 4624 | are also multiples of GCALIGNMENT. */ |
| 4633 | 4625 | ||
| 4634 | static bool | 4626 | static bool |
| 4635 | maybe_lisp_pointer (void *p) | 4627 | maybe_lisp_pointer (void *p) |
| 4636 | { | 4628 | { |
| 4637 | return !((intptr_t) p % (USE_LSB_TAG ? GCALIGNMENT : 2)); | 4629 | return (uintptr_t) p % GCALIGNMENT == 0; |
| 4638 | } | 4630 | } |
| 4639 | 4631 | ||
| 4640 | /* If P points to Lisp data, mark that as live if it isn't already | 4632 | /* If P points to Lisp data, mark that as live if it isn't already |
| @@ -4722,27 +4714,6 @@ mark_maybe_pointer (void *p) | |||
| 4722 | miss objects if __alignof__ were used. */ | 4714 | miss objects if __alignof__ were used. */ |
| 4723 | #define GC_POINTER_ALIGNMENT alignof (void *) | 4715 | #define GC_POINTER_ALIGNMENT alignof (void *) |
| 4724 | 4716 | ||
| 4725 | /* Define POINTERS_MIGHT_HIDE_IN_OBJECTS to 1 if marking via C pointers does | ||
| 4726 | not suffice, which is the typical case. A host where a Lisp_Object is | ||
| 4727 | wider than a pointer might allocate a Lisp_Object in non-adjacent halves. | ||
| 4728 | If USE_LSB_TAG, the bottom half is not a valid pointer, but it should | ||
| 4729 | suffice to widen it to to a Lisp_Object and check it that way. */ | ||
| 4730 | #if USE_LSB_TAG || VAL_MAX < UINTPTR_MAX | ||
| 4731 | # if !USE_LSB_TAG && VAL_MAX < UINTPTR_MAX >> GCTYPEBITS | ||
| 4732 | /* If tag bits straddle pointer-word boundaries, neither mark_maybe_pointer | ||
| 4733 | nor mark_maybe_object can follow the pointers. This should not occur on | ||
| 4734 | any practical porting target. */ | ||
| 4735 | # error "MSB type bits straddle pointer-word boundaries" | ||
| 4736 | # endif | ||
| 4737 | /* Marking via C pointers does not suffice, because Lisp_Objects contain | ||
| 4738 | pointer words that hold pointers ORed with type bits. */ | ||
| 4739 | # define POINTERS_MIGHT_HIDE_IN_OBJECTS 1 | ||
| 4740 | #else | ||
| 4741 | /* Marking via C pointers suffices, because Lisp_Objects contain pointer | ||
| 4742 | words that hold unmodified pointers. */ | ||
| 4743 | # define POINTERS_MIGHT_HIDE_IN_OBJECTS 0 | ||
| 4744 | #endif | ||
| 4745 | |||
| 4746 | /* Mark Lisp objects referenced from the address range START+OFFSET..END | 4717 | /* Mark Lisp objects referenced from the address range START+OFFSET..END |
| 4747 | or END+OFFSET..START. */ | 4718 | or END+OFFSET..START. */ |
| 4748 | 4719 | ||
| @@ -4788,8 +4759,7 @@ mark_memory (void *start, void *end) | |||
| 4788 | { | 4759 | { |
| 4789 | void *p = *(void **) ((char *) pp + i); | 4760 | void *p = *(void **) ((char *) pp + i); |
| 4790 | mark_maybe_pointer (p); | 4761 | mark_maybe_pointer (p); |
| 4791 | if (POINTERS_MIGHT_HIDE_IN_OBJECTS) | 4762 | mark_maybe_object (XIL ((intptr_t) p)); |
| 4792 | mark_maybe_object (XIL ((intptr_t) p)); | ||
| 4793 | } | 4763 | } |
| 4794 | } | 4764 | } |
| 4795 | 4765 | ||
| @@ -5148,22 +5118,13 @@ static void * | |||
| 5148 | pure_alloc (size_t size, int type) | 5118 | pure_alloc (size_t size, int type) |
| 5149 | { | 5119 | { |
| 5150 | void *result; | 5120 | void *result; |
| 5151 | #if USE_LSB_TAG | ||
| 5152 | size_t alignment = GCALIGNMENT; | ||
| 5153 | #else | ||
| 5154 | size_t alignment = alignof (EMACS_INT); | ||
| 5155 | |||
| 5156 | /* Give Lisp_Floats an extra alignment. */ | ||
| 5157 | if (type == Lisp_Float) | ||
| 5158 | alignment = alignof (struct Lisp_Float); | ||
| 5159 | #endif | ||
| 5160 | 5121 | ||
| 5161 | again: | 5122 | again: |
| 5162 | if (type >= 0) | 5123 | if (type >= 0) |
| 5163 | { | 5124 | { |
| 5164 | /* Allocate space for a Lisp object from the beginning of the free | 5125 | /* Allocate space for a Lisp object from the beginning of the free |
| 5165 | space with taking account of alignment. */ | 5126 | space with taking account of alignment. */ |
| 5166 | result = ALIGN (purebeg + pure_bytes_used_lisp, alignment); | 5127 | result = ALIGN (purebeg + pure_bytes_used_lisp, GCALIGNMENT); |
| 5167 | pure_bytes_used_lisp = ((char *)result - (char *)purebeg) + size; | 5128 | pure_bytes_used_lisp = ((char *)result - (char *)purebeg) + size; |
| 5168 | } | 5129 | } |
| 5169 | else | 5130 | else |
diff --git a/src/lisp.h b/src/lisp.h index 198f116fe02..c3289c9d700 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -278,10 +278,7 @@ error !; | |||
| 278 | #endif | 278 | #endif |
| 279 | 279 | ||
| 280 | #ifndef alignas | 280 | #ifndef alignas |
| 281 | # define alignas(alignment) /* empty */ | 281 | # error "alignas not defined" |
| 282 | # if USE_LSB_TAG | ||
| 283 | # error "USE_LSB_TAG requires alignas" | ||
| 284 | # endif | ||
| 285 | #endif | 282 | #endif |
| 286 | 283 | ||
| 287 | #ifdef HAVE_STRUCT_ATTRIBUTE_ALIGNED | 284 | #ifdef HAVE_STRUCT_ATTRIBUTE_ALIGNED |
| @@ -731,9 +728,7 @@ struct Lisp_Symbol | |||
| 731 | 728 | ||
| 732 | /* Yield an integer that contains a symbol tag along with OFFSET. | 729 | /* Yield an integer that contains a symbol tag along with OFFSET. |
| 733 | OFFSET should be the offset in bytes from 'lispsym' to the symbol. */ | 730 | OFFSET should be the offset in bytes from 'lispsym' to the symbol. */ |
| 734 | #define TAG_SYMOFFSET(offset) \ | 731 | #define TAG_SYMOFFSET(offset) TAG_PTR (Lisp_Symbol, offset) |
| 735 | TAG_PTR (Lisp_Symbol, \ | ||
| 736 | ((uintptr_t) (offset) >> (USE_LSB_TAG ? 0 : GCTYPEBITS))) | ||
| 737 | 732 | ||
| 738 | /* XLI_BUILTIN_LISPSYM (iQwhatever) is equivalent to | 733 | /* XLI_BUILTIN_LISPSYM (iQwhatever) is equivalent to |
| 739 | XLI (builtin_lisp_symbol (Qwhatever)), | 734 | XLI (builtin_lisp_symbol (Qwhatever)), |
| @@ -899,8 +894,6 @@ INLINE struct Lisp_Symbol * | |||
| 899 | XSYMBOL (Lisp_Object a) | 894 | XSYMBOL (Lisp_Object a) |
| 900 | { | 895 | { |
| 901 | uintptr_t i = (uintptr_t) XUNTAG (a, Lisp_Symbol); | 896 | uintptr_t i = (uintptr_t) XUNTAG (a, Lisp_Symbol); |
| 902 | if (! USE_LSB_TAG) | ||
| 903 | i <<= GCTYPEBITS; | ||
| 904 | void *p = (char *) lispsym + i; | 897 | void *p = (char *) lispsym + i; |
| 905 | return p; | 898 | return p; |
| 906 | } | 899 | } |