diff options
| author | Eli Zaretskii | 2011-05-09 05:59:23 -0400 |
|---|---|---|
| committer | Eli Zaretskii | 2011-05-09 05:59:23 -0400 |
| commit | 14fe7b530dc927a88169a841afc0cd806593dea8 (patch) | |
| tree | 510192ce4c22c74ffec5b97327ea5e4a03a5a66c /src/alloc.c | |
| parent | 6eea50c73be34e865dabf14cbd2d0e7c4f64e6a0 (diff) | |
| download | emacs-14fe7b530dc927a88169a841afc0cd806593dea8.tar.gz emacs-14fe7b530dc927a88169a841afc0cd806593dea8.zip | |
Backport revisions 2011-04-24T05:30:24Z!eggert@cs.ucla.edu..2011-04-25T19:40:22Z!eggert@cs.ucla.edu (inclusive) from trunk (bug#8623)
The next log entry shows the actual changes by Paul Eggert.
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.
src/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.
src/lisp.h: Say "vectorlike header" rather than "vector header.
(struct vectorlike_header): Rename from struct vector_header.
(XVECTORLIKE_HEADER_SIZE): Renamed from XVECTOR_HEADER_SIZE.
All uses changed.
(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.
src/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".
src/buffer.h (struct buffer): Likewise.
src/font.h (struct font_spec, struct font_entity, struct font): Likewise.
src/frame.h (struct frame): Likewise.
src/process.h (struct Lisp_Process): Likewise.
src/termhooks.h (struct terminal): Likewise.
src/window.c (struct save_window_data, struct saved_window): Likewise.
src/window.h (struct window): Likewise.
src/alloc.c (allocate_buffer, Fmake_bool_vector, allocate_pseudovector):
Use XSETPVECTYPESIZE, not XSETPVECTYPE, to avoid aliasing problems.
src/buffer.c (init_buffer_once): Likewise.
src/lread.c (defsubr): Use XSETTYPED_PVECTYPE, since Lisp_Subr is a
special case.
src/process.c (Fformat_network_address): Use local var for size,
for brevity.
src/fns.c (vector): Remove; this old hack is no longer needed.
src/bytecode.c (exec_byte_code): Don't use XVECTOR before CHECK_VECTOR.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 62 |
1 files changed, 30 insertions, 32 deletions
diff --git a/src/alloc.c b/src/alloc.c index ad11e215da7..77b870f4754 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -163,9 +163,9 @@ static __malloc_size_t bytes_used_when_reconsidered; | |||
| 163 | #define UNMARK_STRING(S) ((S)->size &= ~ARRAY_MARK_FLAG) | 163 | #define UNMARK_STRING(S) ((S)->size &= ~ARRAY_MARK_FLAG) |
| 164 | #define STRING_MARKED_P(S) (((S)->size & ARRAY_MARK_FLAG) != 0) | 164 | #define STRING_MARKED_P(S) (((S)->size & ARRAY_MARK_FLAG) != 0) |
| 165 | 165 | ||
| 166 | #define VECTOR_MARK(V) ((V)->size |= ARRAY_MARK_FLAG) | 166 | #define VECTOR_MARK(V) ((V)->header.size |= ARRAY_MARK_FLAG) |
| 167 | #define VECTOR_UNMARK(V) ((V)->size &= ~ARRAY_MARK_FLAG) | 167 | #define VECTOR_UNMARK(V) ((V)->header.size &= ~ARRAY_MARK_FLAG) |
| 168 | #define VECTOR_MARKED_P(V) (((V)->size & ARRAY_MARK_FLAG) != 0) | 168 | #define VECTOR_MARKED_P(V) (((V)->header.size & ARRAY_MARK_FLAG) != 0) |
| 169 | 169 | ||
| 170 | /* Value is the number of bytes/chars of S, a pointer to a struct | 170 | /* Value is the number of bytes/chars of S, a pointer to a struct |
| 171 | Lisp_String. This must be used instead of STRING_BYTES (S) or | 171 | Lisp_String. This must be used instead of STRING_BYTES (S) or |
| @@ -1151,8 +1151,9 @@ allocate_buffer () | |||
| 1151 | struct buffer *b | 1151 | struct buffer *b |
| 1152 | = (struct buffer *) lisp_malloc (sizeof (struct buffer), | 1152 | = (struct buffer *) lisp_malloc (sizeof (struct buffer), |
| 1153 | MEM_TYPE_BUFFER); | 1153 | MEM_TYPE_BUFFER); |
| 1154 | b->size = sizeof (struct buffer) / sizeof (EMACS_INT); | 1154 | XSETPVECTYPESIZE (b, PVEC_BUFFER, |
| 1155 | XSETPVECTYPE (b, PVEC_BUFFER); | 1155 | ((sizeof (struct buffer) + sizeof (EMACS_INT) - 1) |
| 1156 | / sizeof (EMACS_INT))); | ||
| 1156 | return b; | 1157 | return b; |
| 1157 | } | 1158 | } |
| 1158 | 1159 | ||
| @@ -2341,10 +2342,8 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) | |||
| 2341 | slot `size' of the struct Lisp_Bool_Vector. */ | 2342 | slot `size' of the struct Lisp_Bool_Vector. */ |
| 2342 | val = Fmake_vector (make_number (length_in_elts + 1), Qnil); | 2343 | val = Fmake_vector (make_number (length_in_elts + 1), Qnil); |
| 2343 | 2344 | ||
| 2344 | /* Get rid of any bits that would cause confusion. */ | 2345 | /* No Lisp_Object to trace in there. */ |
| 2345 | XVECTOR (val)->size = 0; /* No Lisp_Object to trace in there. */ | 2346 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0); |
| 2346 | /* Use XVECTOR (val) rather than `p' because p->size is not TRT. */ | ||
| 2347 | XSETPVECTYPE (XVECTOR (val), PVEC_BOOL_VECTOR); | ||
| 2348 | 2347 | ||
| 2349 | p = XBOOL_VECTOR (val); | 2348 | p = XBOOL_VECTOR (val); |
| 2350 | p->size = XFASTINT (length); | 2349 | p->size = XFASTINT (length); |
| @@ -2943,7 +2942,7 @@ allocate_vectorlike (len) | |||
| 2943 | consing_since_gc += nbytes; | 2942 | consing_since_gc += nbytes; |
| 2944 | vector_cells_consed += len; | 2943 | vector_cells_consed += len; |
| 2945 | 2944 | ||
| 2946 | p->next = all_vectors; | 2945 | p->header.next.vector = all_vectors; |
| 2947 | all_vectors = p; | 2946 | all_vectors = p; |
| 2948 | 2947 | ||
| 2949 | MALLOC_UNBLOCK_INPUT; | 2948 | MALLOC_UNBLOCK_INPUT; |
| @@ -2960,7 +2959,7 @@ allocate_vector (nslots) | |||
| 2960 | EMACS_INT nslots; | 2959 | EMACS_INT nslots; |
| 2961 | { | 2960 | { |
| 2962 | struct Lisp_Vector *v = allocate_vectorlike (nslots); | 2961 | struct Lisp_Vector *v = allocate_vectorlike (nslots); |
| 2963 | v->size = nslots; | 2962 | v->header.size = nslots; |
| 2964 | return v; | 2963 | return v; |
| 2965 | } | 2964 | } |
| 2966 | 2965 | ||
| @@ -2976,11 +2975,10 @@ allocate_pseudovector (memlen, lisplen, tag) | |||
| 2976 | EMACS_INT i; | 2975 | EMACS_INT i; |
| 2977 | 2976 | ||
| 2978 | /* Only the first lisplen slots will be traced normally by the GC. */ | 2977 | /* Only the first lisplen slots will be traced normally by the GC. */ |
| 2979 | v->size = lisplen; | ||
| 2980 | for (i = 0; i < lisplen; ++i) | 2978 | for (i = 0; i < lisplen; ++i) |
| 2981 | v->contents[i] = Qnil; | 2979 | v->contents[i] = Qnil; |
| 2982 | 2980 | ||
| 2983 | XSETPVECTYPE (v, tag); /* Add the appropriate tag. */ | 2981 | XSETPVECTYPESIZE (v, tag, lisplen); |
| 2984 | return v; | 2982 | return v; |
| 2985 | } | 2983 | } |
| 2986 | 2984 | ||
| @@ -4884,7 +4882,7 @@ make_pure_vector (len) | |||
| 4884 | 4882 | ||
| 4885 | p = (struct Lisp_Vector *) pure_alloc (size, Lisp_Vectorlike); | 4883 | p = (struct Lisp_Vector *) pure_alloc (size, Lisp_Vectorlike); |
| 4886 | XSETVECTOR (new, p); | 4884 | XSETVECTOR (new, p); |
| 4887 | XVECTOR (new)->size = len; | 4885 | XVECTOR (new)->header.size = len; |
| 4888 | return new; | 4886 | return new; |
| 4889 | } | 4887 | } |
| 4890 | 4888 | ||
| @@ -4916,7 +4914,7 @@ Does not copy symbols. Copies strings without text properties. */) | |||
| 4916 | register int i; | 4914 | register int i; |
| 4917 | EMACS_INT size; | 4915 | EMACS_INT size; |
| 4918 | 4916 | ||
| 4919 | size = XVECTOR (obj)->size; | 4917 | size = XVECTOR_SIZE (obj); |
| 4920 | if (size & PSEUDOVECTOR_FLAG) | 4918 | if (size & PSEUDOVECTOR_FLAG) |
| 4921 | size &= PSEUDOVECTOR_SIZE_MASK; | 4919 | size &= PSEUDOVECTOR_SIZE_MASK; |
| 4922 | vec = XVECTOR (make_pure_vector (size)); | 4920 | vec = XVECTOR (make_pure_vector (size)); |
| @@ -5038,7 +5036,7 @@ returns nil, because real GC can't be done. */) | |||
| 5038 | } | 5036 | } |
| 5039 | } | 5037 | } |
| 5040 | 5038 | ||
| 5041 | nextb = nextb->next; | 5039 | nextb = nextb->header.next.buffer; |
| 5042 | } | 5040 | } |
| 5043 | } | 5041 | } |
| 5044 | 5042 | ||
| @@ -5184,7 +5182,7 @@ returns nil, because real GC can't be done. */) | |||
| 5184 | undo_list any more, we can finally mark the list. */ | 5182 | undo_list any more, we can finally mark the list. */ |
| 5185 | mark_object (nextb->undo_list); | 5183 | mark_object (nextb->undo_list); |
| 5186 | 5184 | ||
| 5187 | nextb = nextb->next; | 5185 | nextb = nextb->header.next.buffer; |
| 5188 | } | 5186 | } |
| 5189 | } | 5187 | } |
| 5190 | 5188 | ||
| @@ -5361,7 +5359,7 @@ static void | |||
| 5361 | mark_vectorlike (ptr) | 5359 | mark_vectorlike (ptr) |
| 5362 | struct Lisp_Vector *ptr; | 5360 | struct Lisp_Vector *ptr; |
| 5363 | { | 5361 | { |
| 5364 | register EMACS_INT size = ptr->size; | 5362 | register EMACS_UINT size = ptr->header.size; |
| 5365 | register int i; | 5363 | register int i; |
| 5366 | 5364 | ||
| 5367 | eassert (!VECTOR_MARKED_P (ptr)); | 5365 | eassert (!VECTOR_MARKED_P (ptr)); |
| @@ -5385,7 +5383,7 @@ static void | |||
| 5385 | mark_char_table (ptr) | 5383 | mark_char_table (ptr) |
| 5386 | struct Lisp_Vector *ptr; | 5384 | struct Lisp_Vector *ptr; |
| 5387 | { | 5385 | { |
| 5388 | register EMACS_INT size = ptr->size & PSEUDOVECTOR_SIZE_MASK; | 5386 | register EMACS_UINT size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; |
| 5389 | register int i; | 5387 | register int i; |
| 5390 | 5388 | ||
| 5391 | eassert (!VECTOR_MARKED_P (ptr)); | 5389 | eassert (!VECTOR_MARKED_P (ptr)); |
| @@ -5500,7 +5498,7 @@ mark_object (arg) | |||
| 5500 | if (po != &buffer_defaults && po != &buffer_local_symbols) | 5498 | if (po != &buffer_defaults && po != &buffer_local_symbols) |
| 5501 | { | 5499 | { |
| 5502 | struct buffer *b; | 5500 | struct buffer *b; |
| 5503 | for (b = all_buffers; b && b != po; b = b->next) | 5501 | for (b = all_buffers; b && b != po; b = b->header.next.buffer) |
| 5504 | ; | 5502 | ; |
| 5505 | if (b == NULL) | 5503 | if (b == NULL) |
| 5506 | abort (); | 5504 | abort (); |
| @@ -5516,7 +5514,7 @@ mark_object (arg) | |||
| 5516 | recursion there. */ | 5514 | recursion there. */ |
| 5517 | { | 5515 | { |
| 5518 | register struct Lisp_Vector *ptr = XVECTOR (obj); | 5516 | register struct Lisp_Vector *ptr = XVECTOR (obj); |
| 5519 | register EMACS_INT size = ptr->size; | 5517 | register EMACS_UINT size = ptr->header.size; |
| 5520 | register int i; | 5518 | register int i; |
| 5521 | 5519 | ||
| 5522 | CHECK_LIVE (live_vector_p); | 5520 | CHECK_LIVE (live_vector_p); |
| @@ -6150,10 +6148,10 @@ gc_sweep () | |||
| 6150 | if (!VECTOR_MARKED_P (buffer)) | 6148 | if (!VECTOR_MARKED_P (buffer)) |
| 6151 | { | 6149 | { |
| 6152 | if (prev) | 6150 | if (prev) |
| 6153 | prev->next = buffer->next; | 6151 | prev->header.next = buffer->header.next; |
| 6154 | else | 6152 | else |
| 6155 | all_buffers = buffer->next; | 6153 | all_buffers = buffer->header.next.buffer; |
| 6156 | next = buffer->next; | 6154 | next = buffer->header.next.buffer; |
| 6157 | lisp_free (buffer); | 6155 | lisp_free (buffer); |
| 6158 | buffer = next; | 6156 | buffer = next; |
| 6159 | } | 6157 | } |
| @@ -6161,7 +6159,7 @@ gc_sweep () | |||
| 6161 | { | 6159 | { |
| 6162 | VECTOR_UNMARK (buffer); | 6160 | VECTOR_UNMARK (buffer); |
| 6163 | UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer)); | 6161 | UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer)); |
| 6164 | prev = buffer, buffer = buffer->next; | 6162 | prev = buffer, buffer = buffer->header.next.buffer; |
| 6165 | } | 6163 | } |
| 6166 | } | 6164 | } |
| 6167 | 6165 | ||
| @@ -6174,10 +6172,10 @@ gc_sweep () | |||
| 6174 | if (!VECTOR_MARKED_P (vector)) | 6172 | if (!VECTOR_MARKED_P (vector)) |
| 6175 | { | 6173 | { |
| 6176 | if (prev) | 6174 | if (prev) |
| 6177 | prev->next = vector->next; | 6175 | prev->header.next = vector->header.next; |
| 6178 | else | 6176 | else |
| 6179 | all_vectors = vector->next; | 6177 | all_vectors = vector->header.next.vector; |
| 6180 | next = vector->next; | 6178 | next = vector->header.next.vector; |
| 6181 | lisp_free (vector); | 6179 | lisp_free (vector); |
| 6182 | n_vectors--; | 6180 | n_vectors--; |
| 6183 | vector = next; | 6181 | vector = next; |
| @@ -6186,11 +6184,11 @@ gc_sweep () | |||
| 6186 | else | 6184 | else |
| 6187 | { | 6185 | { |
| 6188 | VECTOR_UNMARK (vector); | 6186 | VECTOR_UNMARK (vector); |
| 6189 | if (vector->size & PSEUDOVECTOR_FLAG) | 6187 | if (vector->header.size & PSEUDOVECTOR_FLAG) |
| 6190 | total_vector_size += (PSEUDOVECTOR_SIZE_MASK & vector->size); | 6188 | total_vector_size += PSEUDOVECTOR_SIZE_MASK & vector->header.size; |
| 6191 | else | 6189 | else |
| 6192 | total_vector_size += vector->size; | 6190 | total_vector_size += vector->header.size; |
| 6193 | prev = vector, vector = vector->next; | 6191 | prev = vector, vector = vector->header.next.vector; |
| 6194 | } | 6192 | } |
| 6195 | } | 6193 | } |
| 6196 | 6194 | ||