diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2011-04-25 00:14:46 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2011-04-25 00:14:46 -0700 |
commit | eab3844f965646b62e242aa622754b86d1fd3444 (patch) | |
tree | 10246105e5facc5d61ccf797dfa05debdb1877c1 /src/buffer.h | |
parent | 0df1eac54fdf82a80a7611fe421d94a23ebd4a0a (diff) | |
download | emacs-eab3844f965646b62e242aa622754b86d1fd3444.tar.gz emacs-eab3844f965646b62e242aa622754b86d1fd3444.tar.bz2 emacs-eab3844f965646b62e242aa622754b86d1fd3444.zip |
lisp.h: Fix a problem with aliasing and vector headers.
GCC 4.6.0 optimizes based on type-based alias analysis. For
example, if b is of type struct buffer * and v of type struct
Lisp_Vector *, then gcc -O2 was incorrectly assuming that &b->size
!= &v->size, and therefore "v->size = 1; b->size = 2; return
v->size;" must therefore return 1. This assumption is incorrect
for Emacs, since it type-puns struct Lisp_Vector * with many other
types. To fix this problem, this patch adds a new type struct
vector_header that documents the constraints on layout of vectors
and pseudovectors, and helps optimizing compilers not get fooled
by Emacs's type punning. It also adds the macros XSETTYPED_PVECTYPE
XSETTYPED_PSEUDOVECTOR, TYPED_PSEUDOVECTORP, for similar reasons.
* lisp.h (XVECTOR_SIZE): New convenience macro. All previous uses of
XVECTOR (foo)->size replaced to use this macro, to avoid the hassle
of writing XVECTOR (foo)->header.size.
(XVECTOR_HEADER_SIZE): New macro, for use in XSETPSEUDOVECTOR.
(XSETTYPED_PVECTYPE): New macro, specifying the name of the size
member.
(XSETPVECTYPE): Rewrite in terms of new macro.
(XSETPVECTYPESIZE): New macro, specifying both type and size.
This is a bit clearer, and further avoids the possibility of
undesirable aliasing.
(XSETTYPED_PSEUDOVECTOR): New macro, specifying the size.
(XSETPSEUDOVECTOR): Rewrite in terms of XSETTYPED_PSEUDOVECTOR
and XVECTOR_HEADER_SIZE.
(XSETSUBR): Rewrite in terms of XSETTYPED_PSEUDOVECTOR and XSIZE,
since Lisp_Subr is a special case (no "next" field).
(ASIZE): Rewrite in terms of XVECTOR_SIZE.
(struct vector_header): New type.
(TYPED_PSEUDOVECTORP): New macro, also specifying the C type of the
object, to help avoid aliasing.
(PSEUDOVECTORP): Rewrite in terms of TYPED_PSEUDOVECTORP.
(SUBRP): Likewise, since Lisp_Subr is a special case.
* lisp.h (struct Lisp_Vector, struct Lisp_Char_Table):
(struct Lisp_Sub_Char_Table, struct Lisp_Bool_Vector):
(struct Lisp_Hash_Table): Combine first two members into a single
struct vector_header member. All uses of "size" and "next" members
changed to be "header.size" and "header.next".
* buffer.h (struct buffer): Likewise.
* font.h (struct font_spec, struct font_entity, struct font): Likewise.
* frame.h (struct frame): Likewise.
* process.h (struct Lisp_Process): Likewise.
* termhooks.h (struct terminal): Likewise.
* window.c (struct save_window_data, struct saved_window): Likewise.
* window.h (struct window): Likewise.
* alloc.c (allocate_buffer, Fmake_bool_vector, allocate_pseudovector):
Use XSETPVECTYPESIZE, not XSETPVECTYPE, to avoid aliasing problems.
* buffer.c (init_buffer_once): Likewise.
* lread.c (defsubr): Use XSETTYPED_PVECTYPE, since Lisp_Subr is a
special case.
* process.c (Fformat_network_address): Use local var for size,
for brevity.
Diffstat (limited to 'src/buffer.h')
-rw-r--r-- | src/buffer.h | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/src/buffer.h b/src/buffer.h index 2963aa382ca..51b318218cc 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -499,14 +499,13 @@ struct buffer Check out mark_buffer (alloc.c) to see why. */ - EMACS_UINT size; - - /* Next buffer, in chain of all buffers including killed buffers. + /* HEADER.NEXT is the next buffer, in chain of all buffers, + including killed buffers. This chain is used only for garbage collection, in order to collect killed buffers properly. Note that vectors and most pseudovectors are all on one chain, but buffers are on a separate chain of their own. */ - struct buffer *next; + struct vector_header header; /* This structure holds the coordinates of the buffer contents in ordinary buffers. In indirect buffers, this is not used. */ |