#define COMMON_MULTIPLE(a, b) \
((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b))
-/* A lower bound on the alignment of malloc. Although this bound is
- incorrect for some buggy malloc implementations (e.g., MinGW circa
- 2020), the bugs should not matter for the way this bound is used
- since the correct bound is also a multiple of LISP_ALIGNMENT on the
- buggy platforms. */
-enum { MALLOC_ALIGNMENT_BOUND = alignof (max_align_t) };
-
-/* A lower bound on the alignment of Lisp objects allocated on the heap.
- All such objects must have an address that is a multiple of LISP_ALIGNMENT;
- otherwise maybe_lisp_pointer can issue false negatives, causing crashes.
- On all practical Emacs targets, sizeof (struct Lisp_Float) == 8 and
- since GCALIGNMENT also equals 8 there's little point to optimizing
- for impractical targets. */
-enum { LISP_ALIGNMENT = GCALIGNMENT };
+/* Alignment needed for memory blocks that are allocated via malloc
+ and that contain Lisp objects. On typical hosts malloc already
+ aligns sufficiently, but extra work is needed on oddball hosts
+ where Emacs would crash if malloc returned a non-GCALIGNED pointer. */
+enum { LISP_ALIGNMENT = alignof (union { union emacs_align_type x;
+ GCALIGNED_UNION_MEMBER }) };
+verify (LISP_ALIGNMENT % GCALIGNMENT == 0);
/* True if malloc (N) is known to return storage suitably aligned for
- Lisp objects whenever N is a multiple of LISP_ALIGNMENT. */
-enum { MALLOC_IS_LISP_ALIGNED = MALLOC_ALIGNMENT_BOUND % LISP_ALIGNMENT == 0 };
+ Lisp objects whenever N is a multiple of LISP_ALIGNMENT. In
+ practice this is true whenever alignof (max_align_t) is also a
+ multiple of LISP_ALIGNMENT. This works even for buggy platforms
+ like MinGW circa 2020, where alignof (max_align_t) is 16 even though
+ the malloc alignment is only 8, and where Emacs still works because
+ it never does anything that requires an alignment of 16. */
+enum { MALLOC_IS_LISP_ALIGNED = alignof (max_align_t) % LISP_ALIGNMENT == 0 };
/* If compiled with XMALLOC_BLOCK_INPUT_CHECK, define a symbol
BLOCK_INPUT_IN_MEMORY_ALLOCATORS that is visible to the debugger.
collected, and false otherwise (i.e., false if it is easy to see
that P cannot point to Lisp data that can be garbage collected).
Symbols are implemented via offsets not pointers, but the offsets
- are also multiples of LISP_ALIGNMENT. */
+ are also multiples of GCALIGNMENT. */
static bool
maybe_lisp_pointer (void *p)
{
- return (uintptr_t) p % LISP_ALIGNMENT == 0;
+ return (uintptr_t) p % GCALIGNMENT == 0;
}
/* If P points to Lisp data, mark that as live if it isn't already
allocation in a containing union that has GCALIGNED_UNION_MEMBER)
and does not contain a GC-aligned struct or union, putting
GCALIGNED_STRUCT after its closing '}' can help the compiler
- generate better code.
+ generate better code. Also, such structs should be added to the
+ emacs_align_type union.
Although these macros are reasonably portable, they are not
guaranteed on non-GCC platforms, as C11 does not require support
maybe_garbage_collect ();
}
+/* A type with alignment at least as large as any object that Emacs
+ allocates. This is not max_align_t because some platforms (e.g.,
+ mingw) have buggy malloc implementations that do not align for
+ max_align_t. This union contains types of all GCALIGNED_STRUCT
+ components visible here. */
+union emacs_align_type
+{
+ struct Lisp_Bool_Vector Lisp_Bool_Vector;
+ struct Lisp_Char_Table Lisp_Char_Table;
+ struct Lisp_CondVar Lisp_CondVar;
+ struct Lisp_Finalizer Lisp_Finalizer;
+ struct Lisp_Float Lisp_Float;
+ struct Lisp_Hash_Table Lisp_Hash_Table;
+ struct Lisp_Marker Lisp_Marker;
+ struct Lisp_Misc_Ptr Lisp_Misc_Ptr;
+ struct Lisp_Mutex Lisp_Mutex;
+ struct Lisp_Overlay Lisp_Overlay;
+ struct Lisp_Sub_Char_Table Lisp_Sub_Char_Table;
+ struct Lisp_Subr Lisp_Subr;
+ struct Lisp_User_Ptr Lisp_User_Ptr;
+ struct Lisp_Vector Lisp_Vector;
+ struct thread_state thread_state;
+
+ /* Omit the following since they would require including bignum.h,
+ frame.h etc., and in practice their alignments never exceed that
+ of the structs already listed. */
+#if 0
+ struct frame frame;
+ struct Lisp_Bignum Lisp_Bignum;
+ struct Lisp_Module_Function Lisp_Module_Function;
+ struct Lisp_Process Lisp_Process;
+ struct save_window_data save_window_data;
+ struct scroll_bar scroll_bar;
+ struct terminal terminal;
+ struct window window;
+ struct xwidget xwidget;
+ struct xwidget_view xwidget_view;
+#endif
+};
+
INLINE_HEADER_END
#endif /* EMACS_LISP_H */