From 7c5ee88ecb336a2deac1c1b98753f08ef0a2bd1c Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 7 Oct 2011 00:23:44 -0700 Subject: [PATCH] Fix alignment-related core dump during GC. * configure.in (GC_LISP_OBJECT_ALIGNMENT): Remove. This is now done by src/alloc.c. * src/alloc.c (GC_LISP_OBJECT_ALIGNMENT): Use offsetof, not __alignof__ or sizeof. __alignof__ gives the wrong answer on Fedora x86-64 with GCC 4.6.1 when configured with CC='gcc -m32' --with-wide-int; this makes Emacs dump core during garbage collection on rare occasions. sizeof is obviously inferior to offsetof here, so stick with offsetof. (GC_POINTER_ALIGNMENT): New macro. (mark_memory): Omit 3rd (offset) arg; caller changed. Don't assume EMACS_INT alignment is the same as pointer alignment. --- ChangeLog | 5 +++++ configure.in | 3 --- src/ChangeLog | 12 ++++++++++++ src/alloc.c | 37 +++++++++++++++++-------------------- 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6f17289a614..bdccef5941c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-07 Paul Eggert + + * configure.in (GC_LISP_OBJECT_ALIGNMENT): Remove. + This is now done by src/alloc.c. + 2011-10-02 Richard Stallman * configure.in: Rename xlinux_first_failure to xgnu_linux_first_failure diff --git a/configure.in b/configure.in index b8de80baf5d..57cc4dcded8 100644 --- a/configure.in +++ b/configure.in @@ -3663,9 +3663,6 @@ AH_BOTTOM([ /* GC_SETJMP_WORKS is nearly always appropriate for GCC. */ # define GC_SETJMP_WORKS 1 # endif -# ifndef GC_LISP_OBJECT_ALIGNMENT -# define GC_LISP_OBJECT_ALIGNMENT (__alignof__ (Lisp_Object)) -# endif #endif #endif /* EMACS_CONFIG_H */ diff --git a/src/ChangeLog b/src/ChangeLog index b697ee43376..d2c069b7351 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,15 @@ +2011-10-07 Paul Eggert + + * alloc.c (GC_LISP_OBJECT_ALIGNMENT): Use offsetof, not __alignof__ + or sizeof. __alignof__ gives the wrong answer on Fedora x86-64 + with GCC 4.6.1 when configured with CC='gcc -m32' --with-wide-int; + this makes Emacs dump core during garbage collection on rare + occasions. sizeof is obviously inferior to offsetof here, so + stick with offsetof. + (GC_POINTER_ALIGNMENT): New macro. + (mark_memory): Omit 3rd (offset) arg; caller changed. + Don't assume EMACS_INT alignment is the same as pointer alignment. + 2011-10-03 Stefan Monnier * keyboard.c (read_key_sequence_remapped): New var. diff --git a/src/alloc.c b/src/alloc.c index ead5c8a8ca4..f4db3abbd93 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -393,7 +393,7 @@ static int live_symbol_p (struct mem_node *, void *); static int live_float_p (struct mem_node *, void *); static int live_misc_p (struct mem_node *, void *); static void mark_maybe_object (Lisp_Object); -static void mark_memory (void *, void *, int); +static void mark_memory (void *, void *); static void mem_init (void); static struct mem_node *mem_insert (void *, void *, enum mem_type); static void mem_insert_fixup (struct mem_node *); @@ -4235,14 +4235,20 @@ mark_maybe_pointer (void *p) } +#ifndef GC_LISP_OBJECT_ALIGNMENT +# define GC_LISP_OBJECT_ALIGNMENT offsetof (struct {char a; Lisp_Object b;}, b) +#endif +#define GC_POINTER_ALIGNMENT offsetof (struct {char a; void *b;}, b) + /* Mark Lisp objects referenced from the address range START+OFFSET..END or END+OFFSET..START. */ static void -mark_memory (void *start, void *end, int offset) +mark_memory (void *start, void *end) { Lisp_Object *p; void **pp; + int i; #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES nzombies = 0; @@ -4258,8 +4264,9 @@ mark_memory (void *start, void *end, int offset) } /* Mark Lisp_Objects. */ - for (p = (Lisp_Object *) ((char *) start + offset); (void *) p < end; ++p) - mark_maybe_object (*p); + for (p = start; (void *) p < end; p++) + for (i = 0; i < sizeof *p; i += GC_LISP_OBJECT_ALIGNMENT) + mark_maybe_object (*(Lisp_Object *) ((char *) p + i)); /* Mark Lisp data pointed to. This is necessary because, in some situations, the C compiler optimizes Lisp objects away, so that @@ -4279,8 +4286,9 @@ mark_memory (void *start, void *end, int offset) away. The only reference to the life string is through the pointer `s'. */ - for (pp = (void **) ((char *) start + offset); (void *) pp < end; ++pp) - mark_maybe_pointer (*pp); + for (pp = start; (void *) pp < end; pp++) + for (i = 0; i < sizeof *pp; i += GC_POINTER_ALIGNMENT) + mark_maybe_pointer (*(void **) ((char *) pp + i)); } /* setjmp will work with GCC unless NON_SAVING_SETJMP is defined in @@ -4454,15 +4462,11 @@ dump_zombies (void) pass starting at the start of the stack + 2. Likewise, if the minimal alignment of Lisp_Objects on the stack is 1, four passes would be necessary, each one starting with one byte more offset - from the stack start. - - The current code assumes by default that Lisp_Objects are aligned - equally on the stack. */ + from the stack start. */ static void mark_stack (void) { - int i; void *end; #ifdef HAVE___BUILTIN_UNWIND_INIT @@ -4520,15 +4524,8 @@ mark_stack (void) /* This assumes that the stack is a contiguous region in memory. If that's not the case, something has to be done here to iterate over the stack segments. */ -#ifndef GC_LISP_OBJECT_ALIGNMENT -#ifdef __GNUC__ -#define GC_LISP_OBJECT_ALIGNMENT __alignof__ (Lisp_Object) -#else -#define GC_LISP_OBJECT_ALIGNMENT sizeof (Lisp_Object) -#endif -#endif - for (i = 0; i < sizeof (Lisp_Object); i += GC_LISP_OBJECT_ALIGNMENT) - mark_memory (stack_base, end, i); + mark_memory (stack_base, end); + /* Allow for marking a secondary stack, like the register stack on the ia64. */ #ifdef GC_MARK_SECONDARY_STACK -- 2.11.4.GIT