aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2018-06-13 13:30:29 -0700
committerPaul Eggert2018-06-13 13:31:34 -0700
commit967d2c55ef3908fd378e05b2a0070663ae45f6de (patch)
treeb49c5abdec3a63b16cf339268afdc8db729d6fe7 /src
parentb8478b2ab7ad19c629da9c6b0dfd9a6544a6acee (diff)
downloademacs-967d2c55ef3908fd378e05b2a0070663ae45f6de.tar.gz
emacs-967d2c55ef3908fd378e05b2a0070663ae45f6de.zip
Remove some wrong 8-byte alignment assumptions
Do not assume that 8-byte alignment suffices for all C objects, as some platforms require 16-byte alignment for some objects, and this will start to bite us as time goes on (e.g., if an Emacs module ever uses an object containing a long double, which requires 16-byte alignment on x86-64). Conversely, on !USE_LSB_TAG platforms, do not insist on aligning Lisp objects to a multiple of 8, as this is not needed for high-order tag bits. * src/alloc.c (LISP_ALIGNMENT, MALLOC_IS_LISP_ALIGNED): New constants. (XMALLOC_BASE_ALIGNMENT, XMALLOC_HEADER_ALIGNMENT): Removed. All uses replaced by LISP_ALIGNMENT. (aligned_alloc, laligned, lmalloc, lrealloc, union aligned_Lisp_Misc) (maybe_lisp_pointer, pure_alloc): Use LISP_ALIGNMENT rather than GCALIGNMENT. (aligned_alloc): Do not worry about an alignment of LISP_ALIGNMENT when MALLOC_IS_LISP_ALIGNED, as the code never uses aligned_alloc with alignment == LISP_ALIGNMENT in that case. (__alignof__): Remove. All uses removed. (MALLOC_IS_GC_ALIGNED): Remove. All uses replaced with MALLOC_IS_LISP_ALIGNED. (vector_alignment): Remove. All uses replaced with LISP_ALIGNMENT. * src/alloc.c (mark_maybe_pointer): * src/emacs-module.c (value_to_lisp_bits): Do not assume GCALIGNMENT == 1 << GCTYPEBITS, as GCALIGNMENT is 1 on !USE_LSB_TAG platforms now. * src/lisp.h (GCALIGNMENT) [!USE_LSB_TAG]: Now 1. (struct Lisp_Symbol, union vectorlike_header, struct Lisp_Cons) (struct Lisp_String): Simplify test for verifying alignment.
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c98
-rw-r--r--src/emacs-module.c2
-rw-r--r--src/lisp.h29
3 files changed, 63 insertions, 66 deletions
diff --git a/src/alloc.c b/src/alloc.c
index cde2e4b3407..e5fc6ebeb1a 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -633,6 +633,27 @@ buffer_memory_full (ptrdiff_t nbytes)
633#define COMMON_MULTIPLE(a, b) \ 633#define COMMON_MULTIPLE(a, b) \
634 ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b)) 634 ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b))
635 635
636/* LISP_ALIGNMENT is the alignment of Lisp objects. It must be at
637 least GCALIGNMENT so that pointers can be tagged. It also must be
638 at least as strict as the alignment of all the C types used to
639 implement Lisp objects; since pseudovectors can contain any C type,
640 this is max_align_t. On recent GNU/Linux x86 and x86-64 this can
641 often waste up to 8 bytes, since alignof (max_align_t) is 16 but
642 typical vectors need only an alignment of 8. However, it is not
643 worth the hassle to avoid this waste. */
644enum { LISP_ALIGNMENT = alignof (union { max_align_t x; GCALIGNED_UNION }) };
645verify (LISP_ALIGNMENT % GCALIGNMENT == 0);
646
647/* True if malloc (N) is known to return storage suitably aligned for
648 Lisp objects whenever N is a multiple of LISP_ALIGNMENT. In
649 practice this is true whenever alignof (max_align_t) is also a
650 multiple of LISP_ALIGNMENT. This works even for x86, where some
651 platform combinations (e.g., GCC 7 and later, glibc 2.25 and
652 earlier) have bugs where alignof (max_align_t) is 16 even though
653 the malloc alignment is only 8, and where Emacs still works because
654 it never does anything that requires an alignment of 16. */
655enum { MALLOC_IS_LISP_ALIGNED = alignof (max_align_t) % LISP_ALIGNMENT == 0 };
656
636#ifndef XMALLOC_OVERRUN_CHECK 657#ifndef XMALLOC_OVERRUN_CHECK
637#define XMALLOC_OVERRUN_CHECK_OVERHEAD 0 658#define XMALLOC_OVERRUN_CHECK_OVERHEAD 0
638#else 659#else
@@ -653,18 +674,13 @@ buffer_memory_full (ptrdiff_t nbytes)
653#define XMALLOC_OVERRUN_CHECK_OVERHEAD \ 674#define XMALLOC_OVERRUN_CHECK_OVERHEAD \
654 (2 * XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE) 675 (2 * XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE)
655 676
656#define XMALLOC_BASE_ALIGNMENT alignof (max_align_t)
657
658#define XMALLOC_HEADER_ALIGNMENT \
659 COMMON_MULTIPLE (GCALIGNMENT, XMALLOC_BASE_ALIGNMENT)
660
661/* Define XMALLOC_OVERRUN_SIZE_SIZE so that (1) it's large enough to 677/* Define XMALLOC_OVERRUN_SIZE_SIZE so that (1) it's large enough to
662 hold a size_t value and (2) the header size is a multiple of the 678 hold a size_t value and (2) the header size is a multiple of the
663 alignment that Emacs needs for C types and for USE_LSB_TAG. */ 679 alignment that Emacs needs for C types and for USE_LSB_TAG. */
664#define XMALLOC_OVERRUN_SIZE_SIZE \ 680#define XMALLOC_OVERRUN_SIZE_SIZE \
665 (((XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t) \ 681 (((XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t) \
666 + XMALLOC_HEADER_ALIGNMENT - 1) \ 682 + LISP_ALIGNMENT - 1) \
667 / XMALLOC_HEADER_ALIGNMENT * XMALLOC_HEADER_ALIGNMENT) \ 683 / LISP_ALIGNMENT * LISP_ALIGNMENT) \
668 - XMALLOC_OVERRUN_CHECK_SIZE) 684 - XMALLOC_OVERRUN_CHECK_SIZE)
669 685
670static char const xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE] = 686static char const xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE] =
@@ -1165,9 +1181,11 @@ aligned_alloc (size_t alignment, size_t size)
1165 Verify this for all arguments this function is given. */ 1181 Verify this for all arguments this function is given. */
1166 verify (BLOCK_ALIGN % sizeof (void *) == 0 1182 verify (BLOCK_ALIGN % sizeof (void *) == 0
1167 && POWER_OF_2 (BLOCK_ALIGN / sizeof (void *))); 1183 && POWER_OF_2 (BLOCK_ALIGN / sizeof (void *)));
1168 verify (GCALIGNMENT % sizeof (void *) == 0 1184 verify (MALLOC_IS_LISP_ALIGNED
1169 && POWER_OF_2 (GCALIGNMENT / sizeof (void *))); 1185 || (LISP_ALIGNMENT % sizeof (void *) == 0
1170 eassert (alignment == BLOCK_ALIGN || alignment == GCALIGNMENT); 1186 && POWER_OF_2 (LISP_ALIGNMENT / sizeof (void *))));
1187 eassert (alignment == BLOCK_ALIGN
1188 || (!MALLOC_IS_LISP_ALIGNED && alignment == LISP_ALIGNMENT));
1171 1189
1172 void *p; 1190 void *p;
1173 return posix_memalign (&p, alignment, size) == 0 ? p : 0; 1191 return posix_memalign (&p, alignment, size) == 0 ? p : 0;
@@ -1399,31 +1417,15 @@ lisp_align_free (void *block)
1399 MALLOC_UNBLOCK_INPUT; 1417 MALLOC_UNBLOCK_INPUT;
1400} 1418}
1401 1419
1402#if !defined __GNUC__ && !defined __alignof__
1403# define __alignof__(type) alignof (type)
1404#endif
1405
1406/* True if malloc (N) is known to return a multiple of GCALIGNMENT
1407 whenever N is also a multiple. In practice this is true if
1408 __alignof__ (max_align_t) is a multiple as well, assuming
1409 GCALIGNMENT is 8; other values of GCALIGNMENT have not been looked
1410 into. Use __alignof__ if available, as otherwise
1411 MALLOC_IS_GC_ALIGNED would be false on GCC x86 even though the
1412 alignment is OK there.
1413
1414 This is a macro, not an enum constant, for portability to HP-UX
1415 10.20 cc and AIX 3.2.5 xlc. */
1416#define MALLOC_IS_GC_ALIGNED \
1417 (GCALIGNMENT == 8 && __alignof__ (max_align_t) % GCALIGNMENT == 0)
1418
1419/* True if a malloc-returned pointer P is suitably aligned for SIZE, 1420/* True if a malloc-returned pointer P is suitably aligned for SIZE,
1420 where Lisp alignment may be needed if SIZE is Lisp-aligned. */ 1421 where Lisp object alignment may be needed if SIZE is a multiple of
1422 LISP_ALIGNMENT. */
1421 1423
1422static bool 1424static bool
1423laligned (void *p, size_t size) 1425laligned (void *p, size_t size)
1424{ 1426{
1425 return (MALLOC_IS_GC_ALIGNED || (intptr_t) p % GCALIGNMENT == 0 1427 return (MALLOC_IS_LISP_ALIGNED || (intptr_t) p % LISP_ALIGNMENT == 0
1426 || size % GCALIGNMENT != 0); 1428 || size % LISP_ALIGNMENT != 0);
1427} 1429}
1428 1430
1429/* Like malloc and realloc except that if SIZE is Lisp-aligned, make 1431/* Like malloc and realloc except that if SIZE is Lisp-aligned, make
@@ -1446,8 +1448,8 @@ static void *
1446lmalloc (size_t size) 1448lmalloc (size_t size)
1447{ 1449{
1448#ifdef USE_ALIGNED_ALLOC 1450#ifdef USE_ALIGNED_ALLOC
1449 if (! MALLOC_IS_GC_ALIGNED && size % GCALIGNMENT == 0) 1451 if (! MALLOC_IS_LISP_ALIGNED && size % LISP_ALIGNMENT == 0)
1450 return aligned_alloc (GCALIGNMENT, size); 1452 return aligned_alloc (LISP_ALIGNMENT, size);
1451#endif 1453#endif
1452 1454
1453 while (true) 1455 while (true)
@@ -1456,7 +1458,7 @@ lmalloc (size_t size)
1456 if (laligned (p, size)) 1458 if (laligned (p, size))
1457 return p; 1459 return p;
1458 free (p); 1460 free (p);
1459 size_t bigger = size + GCALIGNMENT; 1461 size_t bigger = size + LISP_ALIGNMENT;
1460 if (size < bigger) 1462 if (size < bigger)
1461 size = bigger; 1463 size = bigger;
1462 } 1464 }
@@ -1470,7 +1472,7 @@ lrealloc (void *p, size_t size)
1470 p = realloc (p, size); 1472 p = realloc (p, size);
1471 if (laligned (p, size)) 1473 if (laligned (p, size))
1472 return p; 1474 return p;
1473 size_t bigger = size + GCALIGNMENT; 1475 size_t bigger = size + LISP_ALIGNMENT;
1474 if (size < bigger) 1476 if (size < bigger)
1475 size = bigger; 1477 size = bigger;
1476 } 1478 }
@@ -2931,16 +2933,8 @@ set_next_vector (struct Lisp_Vector *v, struct Lisp_Vector *p)
2931 2933
2932#define VECTOR_BLOCK_SIZE 4096 2934#define VECTOR_BLOCK_SIZE 4096
2933 2935
2934/* Alignment of struct Lisp_Vector objects. Because pseudovectors
2935 can contain any C type, align at least as strictly as
2936 max_align_t. On x86 and x86-64 this can waste up to 8 bytes
2937 for typical vectors, since alignof (max_align_t) is 16 but
2938 typical vectors need only an alignment of 8. However, it is
2939 not worth the hassle to avoid wasting those bytes. */
2940enum {vector_alignment = COMMON_MULTIPLE (alignof (max_align_t), GCALIGNMENT)};
2941
2942/* Vector size requests are a multiple of this. */ 2936/* Vector size requests are a multiple of this. */
2943enum { roundup_size = COMMON_MULTIPLE (vector_alignment, word_size) }; 2937enum { roundup_size = COMMON_MULTIPLE (LISP_ALIGNMENT, word_size) };
2944 2938
2945/* Verify assumptions described above. */ 2939/* Verify assumptions described above. */
2946verify (VECTOR_BLOCK_SIZE % roundup_size == 0); 2940verify (VECTOR_BLOCK_SIZE % roundup_size == 0);
@@ -3007,7 +3001,7 @@ struct large_vector
3007 3001
3008enum 3002enum
3009{ 3003{
3010 large_vector_offset = ROUNDUP (sizeof (struct large_vector), vector_alignment) 3004 large_vector_offset = ROUNDUP (sizeof (struct large_vector), LISP_ALIGNMENT)
3011}; 3005};
3012 3006
3013static struct Lisp_Vector * 3007static struct Lisp_Vector *
@@ -3656,8 +3650,8 @@ Its value is void, and its function definition and property list are nil. */)
3656union aligned_Lisp_Misc 3650union aligned_Lisp_Misc
3657{ 3651{
3658 union Lisp_Misc m; 3652 union Lisp_Misc m;
3659 unsigned char c[(sizeof (union Lisp_Misc) + GCALIGNMENT - 1) 3653 unsigned char c[(sizeof (union Lisp_Misc) + LISP_ALIGNMENT - 1)
3660 & -GCALIGNMENT]; 3654 & -LISP_ALIGNMENT];
3661}; 3655};
3662 3656
3663/* Allocation of markers and other objects that share that structure. 3657/* Allocation of markers and other objects that share that structure.
@@ -4851,14 +4845,16 @@ mark_maybe_object (Lisp_Object obj)
4851 } 4845 }
4852} 4846}
4853 4847
4854/* Return true if P can point to Lisp data, and false otherwise. 4848/* Return true if P might point to Lisp data that can be garbage
4849 collected, and false otherwise (i.e., false if it is easy to see
4850 that P cannot point to Lisp data that can be garbage collected).
4855 Symbols are implemented via offsets not pointers, but the offsets 4851 Symbols are implemented via offsets not pointers, but the offsets
4856 are also multiples of GCALIGNMENT. */ 4852 are also multiples of LISP_ALIGNMENT. */
4857 4853
4858static bool 4854static bool
4859maybe_lisp_pointer (void *p) 4855maybe_lisp_pointer (void *p)
4860{ 4856{
4861 return (uintptr_t) p % GCALIGNMENT == 0; 4857 return (uintptr_t) p % LISP_ALIGNMENT == 0;
4862} 4858}
4863 4859
4864#ifndef HAVE_MODULES 4860#ifndef HAVE_MODULES
@@ -4887,7 +4883,7 @@ mark_maybe_pointer (void *p)
4887 { 4883 {
4888 /* For the wide-int case, also mark emacs_value tagged pointers, 4884 /* For the wide-int case, also mark emacs_value tagged pointers,
4889 which can be generated by emacs-module.c's value_to_lisp. */ 4885 which can be generated by emacs-module.c's value_to_lisp. */
4890 p = (void *) ((uintptr_t) p & ~(GCALIGNMENT - 1)); 4886 p = (void *) ((uintptr_t) p & ~((1 << GCTYPEBITS) - 1));
4891 } 4887 }
4892 4888
4893 m = mem_find (p); 4889 m = mem_find (p);
@@ -5358,7 +5354,7 @@ pure_alloc (size_t size, int type)
5358 { 5354 {
5359 /* Allocate space for a Lisp object from the beginning of the free 5355 /* Allocate space for a Lisp object from the beginning of the free
5360 space with taking account of alignment. */ 5356 space with taking account of alignment. */
5361 result = pointer_align (purebeg + pure_bytes_used_lisp, GCALIGNMENT); 5357 result = pointer_align (purebeg + pure_bytes_used_lisp, LISP_ALIGNMENT);
5362 pure_bytes_used_lisp = ((char *)result - (char *)purebeg) + size; 5358 pure_bytes_used_lisp = ((char *)result - (char *)purebeg) + size;
5363 } 5359 }
5364 else 5360 else
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 956706cf9f5..c18c7ab308b 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -924,7 +924,7 @@ value_to_lisp_bits (emacs_value v)
924 makes TAG_PTR faster. */ 924 makes TAG_PTR faster. */
925 925
926 intptr_t i = (intptr_t) v; 926 intptr_t i = (intptr_t) v;
927 EMACS_UINT tag = i & (GCALIGNMENT - 1); 927 EMACS_UINT tag = i & ((1 << GCTYPEBITS) - 1);
928 EMACS_UINT untagged = i - tag; 928 EMACS_UINT untagged = i - tag;
929 switch (tag) 929 switch (tag)
930 { 930 {
diff --git a/src/lisp.h b/src/lisp.h
index d4499846053..aaad90b2dad 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -233,10 +233,6 @@ extern bool suppress_checking EXTERNALLY_VISIBLE;
233 233
234enum Lisp_Bits 234enum Lisp_Bits
235 { 235 {
236 /* 2**GCTYPEBITS. This must be a macro that expands to a literal
237 integer constant, for older versions of GCC (through at least 4.9). */
238#define GCALIGNMENT 8
239
240 /* Number of bits in a Lisp_Object value, not counting the tag. */ 236 /* Number of bits in a Lisp_Object value, not counting the tag. */
241 VALBITS = EMACS_INT_WIDTH - GCTYPEBITS, 237 VALBITS = EMACS_INT_WIDTH - GCTYPEBITS,
242 238
@@ -247,10 +243,6 @@ enum Lisp_Bits
247 FIXNUM_BITS = VALBITS + 1 243 FIXNUM_BITS = VALBITS + 1
248 }; 244 };
249 245
250#if GCALIGNMENT != 1 << GCTYPEBITS
251# error "GCALIGNMENT and GCTYPEBITS are inconsistent"
252#endif
253
254/* The maximum value that can be stored in a EMACS_INT, assuming all 246/* The maximum value that can be stored in a EMACS_INT, assuming all
255 bits other than the type bits contribute to a nonnegative signed value. 247 bits other than the type bits contribute to a nonnegative signed value.
256 This can be used in #if, e.g., '#if USE_LSB_TAG' below expands to an 248 This can be used in #if, e.g., '#if USE_LSB_TAG' below expands to an
@@ -277,12 +269,21 @@ DEFINE_GDB_SYMBOL_END (VALMASK)
277error !; 269error !;
278#endif 270#endif
279 271
272/* Minimum alignment requirement for Lisp objects, imposed by the
273 internal representation of tagged pointers. It is 2**GCTYPEBITS if
274 USE_LSB_TAG, 1 otherwise. It must be a literal integer constant,
275 for older versions of GCC (through at least 4.9). */
280#if USE_LSB_TAG 276#if USE_LSB_TAG
281# define GCALIGNED_UNION char alignas (GCALIGNMENT) gcaligned; 277# define GCALIGNMENT 8
278# if GCALIGNMENT != 1 << GCTYPEBITS
279# error "GCALIGNMENT and GCTYPEBITS are inconsistent"
280# endif
282#else 281#else
283# define GCALIGNED_UNION 282# define GCALIGNMENT 1
284#endif 283#endif
285 284
285#define GCALIGNED_UNION char alignas (GCALIGNMENT) gcaligned;
286
286/* Lisp_Word is a scalar word suitable for holding a tagged pointer or 287/* Lisp_Word is a scalar word suitable for holding a tagged pointer or
287 integer. Usually it is a pointer to a deliberately-incomplete type 288 integer. Usually it is a pointer to a deliberately-incomplete type
288 'union Lisp_X'. However, it is EMACS_INT when Lisp_Objects and 289 'union Lisp_X'. However, it is EMACS_INT when Lisp_Objects and
@@ -774,7 +775,7 @@ struct Lisp_Symbol
774 GCALIGNED_UNION 775 GCALIGNED_UNION
775 } u; 776 } u;
776}; 777};
777verify (!USE_LSB_TAG || alignof (struct Lisp_Symbol) % GCALIGNMENT == 0); 778verify (alignof (struct Lisp_Symbol) % GCALIGNMENT == 0);
778 779
779/* Declare a Lisp-callable function. The MAXARGS parameter has the same 780/* Declare a Lisp-callable function. The MAXARGS parameter has the same
780 meaning as in the DEFUN macro, and is used to construct a prototype. */ 781 meaning as in the DEFUN macro, and is used to construct a prototype. */
@@ -888,7 +889,7 @@ union vectorlike_header
888 ptrdiff_t size; 889 ptrdiff_t size;
889 GCALIGNED_UNION 890 GCALIGNED_UNION
890 }; 891 };
891verify (!USE_LSB_TAG || alignof (union vectorlike_header) % GCALIGNMENT == 0); 892verify (alignof (union vectorlike_header) % GCALIGNMENT == 0);
892 893
893INLINE bool 894INLINE bool
894(SYMBOLP) (Lisp_Object x) 895(SYMBOLP) (Lisp_Object x)
@@ -1249,7 +1250,7 @@ struct Lisp_Cons
1249 GCALIGNED_UNION 1250 GCALIGNED_UNION
1250 } u; 1251 } u;
1251}; 1252};
1252verify (!USE_LSB_TAG || alignof (struct Lisp_Cons) % GCALIGNMENT == 0); 1253verify (alignof (struct Lisp_Cons) % GCALIGNMENT == 0);
1253 1254
1254INLINE bool 1255INLINE bool
1255(NILP) (Lisp_Object x) 1256(NILP) (Lisp_Object x)
@@ -1371,7 +1372,7 @@ struct Lisp_String
1371 GCALIGNED_UNION 1372 GCALIGNED_UNION
1372 } u; 1373 } u;
1373}; 1374};
1374verify (!USE_LSB_TAG || alignof (struct Lisp_String) % GCALIGNMENT == 0); 1375verify (alignof (struct Lisp_String) % GCALIGNMENT == 0);
1375 1376
1376INLINE bool 1377INLINE bool
1377STRINGP (Lisp_Object x) 1378STRINGP (Lisp_Object x)