aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c98
1 files changed, 47 insertions, 51 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