aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2015-06-24 20:10:03 -0700
committerPaul Eggert2015-06-24 20:10:44 -0700
commit93f4f67ba93b78e8b31e498e8ce7bce4c8298b76 (patch)
tree788c0808926664ea23de2f903f4c233c5febf7ab /src
parentf230b2ff3136120a9be544a5d3a974f7087ce55b (diff)
downloademacs-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.c59
-rw-r--r--src/lisp.h11
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
3304union aligned_Lisp_Symbol 3300union 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
3416union aligned_Lisp_Misc 3410union 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
4634static bool 4626static bool
4635maybe_lisp_pointer (void *p) 4627maybe_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 *
5148pure_alloc (size_t size, int type) 5118pure_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 *
899XSYMBOL (Lisp_Object a) 894XSYMBOL (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}