aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorEli Zaretskii2011-05-09 05:59:23 -0400
committerEli Zaretskii2011-05-09 05:59:23 -0400
commit14fe7b530dc927a88169a841afc0cd806593dea8 (patch)
tree510192ce4c22c74ffec5b97327ea5e4a03a5a66c /src/alloc.c
parent6eea50c73be34e865dabf14cbd2d0e7c4f64e6a0 (diff)
downloademacs-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.c62
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
5361mark_vectorlike (ptr) 5359mark_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
5385mark_char_table (ptr) 5383mark_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