diff options
| author | Paul Eggert <eggert@cs.ucla.edu> | 2017-11-13 08:51:41 -0800 |
|---|---|---|
| committer | Paul Eggert <eggert@cs.ucla.edu> | 2017-11-13 10:16:51 -0800 |
| commit | b1573a97e17b518723ab3f906eb6d521caed196d (patch) | |
| tree | 2bcfe8f47a99d7ba9b46e75ed5bffd2ba37970e0 /src/buffer.c | |
| parent | 5d68dc9a2fd1b9b883db6bc1c226541b50de8bb1 (diff) | |
| download | emacs-b1573a97e17b518723ab3f906eb6d521caed196d.tar.gz | |
Use alignas to fix GCALIGN-related bugs
Use alignas and unions to specify alignments of objects needing
addresses that are at least a multiple of GCALIGNMENT. Using
these standard C facilities should be safer than relying on ad hoc
and poorly-understood features like GCC’s __attribute__
((aligned (N))), the root cause for recent porting bugs like
Bug#29040. The alignas macro was standardized by C11 and Gnulib
supports alignas for pre-C11 platforms. I have tested this on Sun
Studio 12 sparc (2007) and GCC 4.4.7 x86-64 (2012) as well as on
more recent platforms like GCC 7.2.1 (2017) on Fedora 26 (both
x86-64 and x86).
* lib-src/make-docfile.c (close_emacs_globals): lispsym is now
just an array of struct Lisp_Symbol, since struct Lisp_Symbol is
now properly aligned. All uses changed.
* src/alloc.c (NEXT_FREE_LISP_STRING): Just use the new u.next
member; this is simpler and safer than casting a pointer that
might not be aligned properly.
(aligned_Lisp_Symbol): Remove. No longer needed, now that struct
Lisp_Symbol is aligned properly. All uses replaced with struct
Lisp_Symbol.
* src/lisp.h (GCALIGNED): Remove, as it does not work as expected:
it can cause the natural alignment to be ignored. All uses
replaced by unions with a ‘char alignas (GCALIGNMENT)’ member as
described below.
(struct Lisp_Symbol, struct Lisp_Cons, struct Lisp_String):
Change definition from ‘struct TAG { MEMBERS };’ to
‘struct TAG { union { struct { MEMBERS } s; char alignas
(GCALIGNMENT) gcaligned; } u; };’. This guarantees ‘struct TAG’
to have an alignment that at least max (GCALIGNMENT, N) where N is
its old alignment. All uses like ‘PTR->MEMBER’ changed to
‘PTR->u.s.MEMBER’; these uses were supposed to be mostly private
anyway. Verify that the resulting ‘struct TAG’ is properly
aligned for Emacs.
(union vectorlike_header): New member ‘gcaligned’ to guarantee
that this type, and its containing types like ‘struct Lisp_Subr’,
‘struct buffer’ and ‘struct thread_state’, are all properly
aligned for Emacs.
(struct Lisp_String): New union member ‘next’, for the benefit
of NEXT_FREE_LISP_STRING.
(union Aligned_Cons, union Aligned_String): Remove. All uses
replaced by struct Lisp_Cons and struct Lisp_String, since they
are now properly aligned.
(USE_STACK_CONS, USE_STACK_STRING): Simplify now that we can
assume struct Lisp_Cons and struct Lisp_String are properly
aligned.
Diffstat (limited to 'src/buffer.c')
| -rw-r--r-- | src/buffer.c | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/src/buffer.c b/src/buffer.c index edeed55e8be..4ae5e811b07 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -61,7 +61,7 @@ struct buffer *all_buffers; Setting the default value also goes through the alist of buffers and stores into each buffer that does not say it has a local value. */ -struct GCALIGNED buffer buffer_defaults; +struct buffer buffer_defaults; /* This structure marks which slots in a buffer have corresponding default values in buffer_defaults. @@ -84,7 +84,7 @@ struct buffer buffer_local_flags; /* This structure holds the names of symbols whose values may be buffer-local. It is indexed and accessed in the same way as the above. */ -struct GCALIGNED buffer buffer_local_symbols; +struct buffer buffer_local_symbols; /* Return the symbol of the per-buffer variable at offset OFFSET in the buffer structure. */ @@ -1021,7 +1021,8 @@ reset_buffer_local_variables (struct buffer *b, bool permanent_too) newlist = Fcons (elt, newlist); } newlist = Fnreverse (newlist); - if (XSYMBOL (local_var)->trapped_write == SYMBOL_TRAPPED_WRITE) + if (XSYMBOL (local_var)->u.s.trapped_write + == SYMBOL_TRAPPED_WRITE) notify_variable_watchers (local_var, newlist, Qmakunbound, Fcurrent_buffer ()); XSETCDR (XCAR (tmp), newlist); @@ -1034,7 +1035,7 @@ reset_buffer_local_variables (struct buffer *b, bool permanent_too) else XSETCDR (last, XCDR (tmp)); - if (XSYMBOL (local_var)->trapped_write == SYMBOL_TRAPPED_WRITE) + if (XSYMBOL (local_var)->u.s.trapped_write == SYMBOL_TRAPPED_WRITE) notify_variable_watchers (local_var, Qnil, Qmakunbound, Fcurrent_buffer ()); } @@ -1166,7 +1167,7 @@ buffer_local_value (Lisp_Object variable, Lisp_Object buffer) sym = XSYMBOL (variable); start: - switch (sym->redirect) + switch (sym->u.s.redirect) { case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; case SYMBOL_PLAINVAL: result = SYMBOL_VAL (sym); break; @@ -2096,7 +2097,7 @@ void set_buffer_internal_2 (register struct buffer *b) { Lisp_Object var = XCAR (XCAR (tail)); struct Lisp_Symbol *sym = XSYMBOL (var); - if (sym->redirect == SYMBOL_LOCALIZED /* Just to be sure. */ + if (sym->u.s.redirect == SYMBOL_LOCALIZED /* Just to be sure. */ && SYMBOL_BLV (sym)->fwd) /* Just reference the variable to cause it to become set for this buffer. */ @@ -2752,7 +2753,7 @@ swap_out_buffer_local_variables (struct buffer *b) for (alist = oalist; CONSP (alist); alist = XCDR (alist)) { Lisp_Object sym = XCAR (XCAR (alist)); - eassert (XSYMBOL (sym)->redirect == SYMBOL_LOCALIZED); + eassert (XSYMBOL (sym)->u.s.redirect == SYMBOL_LOCALIZED); /* Need not do anything if some other buffer's binding is now cached. */ if (EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer)) @@ -5423,8 +5424,8 @@ defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring, bo_fwd->type = Lisp_Fwd_Buffer_Obj; bo_fwd->offset = offset; bo_fwd->predicate = predicate; - sym->declared_special = 1; - sym->redirect = SYMBOL_FORWARDED; + sym->u.s.declared_special = true; + sym->u.s.redirect = SYMBOL_FORWARDED; SET_SYMBOL_FWD (sym, (union Lisp_Fwd *) bo_fwd); XSETSYMBOL (PER_BUFFER_SYMBOL (offset), sym); |
