aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert2011-04-25 00:14:46 -0700
committerPaul Eggert2011-04-25 00:14:46 -0700
commiteab3844f965646b62e242aa622754b86d1fd3444 (patch)
tree10246105e5facc5d61ccf797dfa05debdb1877c1 /src/alloc.c
parent0df1eac54fdf82a80a7611fe421d94a23ebd4a0a (diff)
downloademacs-eab3844f965646b62e242aa622754b86d1fd3444.tar.gz
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/alloc.c')
-rw-r--r--src/alloc.c63
1 files changed, 30 insertions, 33 deletions
diff --git a/src/alloc.c b/src/alloc.c
index dd27303428f..c9496ecf25c 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -146,9 +146,9 @@ static pthread_mutex_t alloc_mutex;
146#define UNMARK_STRING(S) ((S)->size &= ~ARRAY_MARK_FLAG) 146#define UNMARK_STRING(S) ((S)->size &= ~ARRAY_MARK_FLAG)
147#define STRING_MARKED_P(S) (((S)->size & ARRAY_MARK_FLAG) != 0) 147#define STRING_MARKED_P(S) (((S)->size & ARRAY_MARK_FLAG) != 0)
148 148
149#define VECTOR_MARK(V) ((V)->size |= ARRAY_MARK_FLAG) 149#define VECTOR_MARK(V) ((V)->header.size |= ARRAY_MARK_FLAG)
150#define VECTOR_UNMARK(V) ((V)->size &= ~ARRAY_MARK_FLAG) 150#define VECTOR_UNMARK(V) ((V)->header.size &= ~ARRAY_MARK_FLAG)
151#define VECTOR_MARKED_P(V) (((V)->size & ARRAY_MARK_FLAG) != 0) 151#define VECTOR_MARKED_P(V) (((V)->header.size & ARRAY_MARK_FLAG) != 0)
152 152
153/* Value is the number of bytes of S, a pointer to a struct Lisp_String. 153/* Value is the number of bytes of S, a pointer to a struct Lisp_String.
154 Be careful during GC, because S->size contains the mark bit for 154 Be careful during GC, because S->size contains the mark bit for
@@ -1055,9 +1055,9 @@ allocate_buffer (void)
1055 struct buffer *b 1055 struct buffer *b
1056 = (struct buffer *) lisp_malloc (sizeof (struct buffer), 1056 = (struct buffer *) lisp_malloc (sizeof (struct buffer),
1057 MEM_TYPE_BUFFER); 1057 MEM_TYPE_BUFFER);
1058 b->size = ((sizeof (struct buffer) + sizeof (EMACS_INT) - 1) 1058 XSETPVECTYPESIZE (b, PVEC_BUFFER,
1059 / sizeof (EMACS_INT)); 1059 ((sizeof (struct buffer) + sizeof (EMACS_INT) - 1)
1060 XSETPVECTYPE (b, PVEC_BUFFER); 1060 / sizeof (EMACS_INT)));
1061 return b; 1061 return b;
1062} 1062}
1063 1063
@@ -2244,10 +2244,8 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */)
2244 slot `size' of the struct Lisp_Bool_Vector. */ 2244 slot `size' of the struct Lisp_Bool_Vector. */
2245 val = Fmake_vector (make_number (length_in_elts + 1), Qnil); 2245 val = Fmake_vector (make_number (length_in_elts + 1), Qnil);
2246 2246
2247 /* Get rid of any bits that would cause confusion. */ 2247 /* No Lisp_Object to trace in there. */
2248 XVECTOR (val)->size = 0; /* No Lisp_Object to trace in there. */ 2248 XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0);
2249 /* Use XVECTOR (val) rather than `p' because p->size is not TRT. */
2250 XSETPVECTYPE (XVECTOR (val), PVEC_BOOL_VECTOR);
2251 2249
2252 p = XBOOL_VECTOR (val); 2250 p = XBOOL_VECTOR (val);
2253 p->size = XFASTINT (length); 2251 p->size = XFASTINT (length);
@@ -2814,7 +2812,7 @@ allocate_vectorlike (EMACS_INT len)
2814 consing_since_gc += nbytes; 2812 consing_since_gc += nbytes;
2815 vector_cells_consed += len; 2813 vector_cells_consed += len;
2816 2814
2817 p->next = all_vectors; 2815 p->header.next.vector = all_vectors;
2818 all_vectors = p; 2816 all_vectors = p;
2819 2817
2820 MALLOC_UNBLOCK_INPUT; 2818 MALLOC_UNBLOCK_INPUT;
@@ -2830,7 +2828,7 @@ struct Lisp_Vector *
2830allocate_vector (EMACS_INT nslots) 2828allocate_vector (EMACS_INT nslots)
2831{ 2829{
2832 struct Lisp_Vector *v = allocate_vectorlike (nslots); 2830 struct Lisp_Vector *v = allocate_vectorlike (nslots);
2833 v->size = nslots; 2831 v->header.size = nslots;
2834 return v; 2832 return v;
2835} 2833}
2836 2834
@@ -2844,11 +2842,10 @@ allocate_pseudovector (int memlen, int lisplen, EMACS_INT tag)
2844 EMACS_INT i; 2842 EMACS_INT i;
2845 2843
2846 /* Only the first lisplen slots will be traced normally by the GC. */ 2844 /* Only the first lisplen slots will be traced normally by the GC. */
2847 v->size = lisplen;
2848 for (i = 0; i < lisplen; ++i) 2845 for (i = 0; i < lisplen; ++i)
2849 v->contents[i] = Qnil; 2846 v->contents[i] = Qnil;
2850 2847
2851 XSETPVECTYPE (v, tag); /* Add the appropriate tag. */ 2848 XSETPVECTYPESIZE (v, tag, lisplen);
2852 return v; 2849 return v;
2853} 2850}
2854 2851
@@ -4737,7 +4734,7 @@ make_pure_vector (EMACS_INT len)
4737 4734
4738 p = (struct Lisp_Vector *) pure_alloc (size, Lisp_Vectorlike); 4735 p = (struct Lisp_Vector *) pure_alloc (size, Lisp_Vectorlike);
4739 XSETVECTOR (new, p); 4736 XSETVECTOR (new, p);
4740 XVECTOR (new)->size = len; 4737 XVECTOR (new)->header.size = len;
4741 return new; 4738 return new;
4742} 4739}
4743 4740
@@ -4775,7 +4772,7 @@ Does not copy symbols. Copies strings without text properties. */)
4775 register EMACS_INT i; 4772 register EMACS_INT i;
4776 EMACS_INT size; 4773 EMACS_INT size;
4777 4774
4778 size = XVECTOR (obj)->size; 4775 size = XVECTOR_SIZE (obj);
4779 if (size & PSEUDOVECTOR_FLAG) 4776 if (size & PSEUDOVECTOR_FLAG)
4780 size &= PSEUDOVECTOR_SIZE_MASK; 4777 size &= PSEUDOVECTOR_SIZE_MASK;
4781 vec = XVECTOR (make_pure_vector (size)); 4778 vec = XVECTOR (make_pure_vector (size));
@@ -4899,7 +4896,7 @@ returns nil, because real GC can't be done. */)
4899 } 4896 }
4900 } 4897 }
4901 4898
4902 nextb = nextb->next; 4899 nextb = nextb->header.next.buffer;
4903 } 4900 }
4904 } 4901 }
4905 4902
@@ -5054,7 +5051,7 @@ returns nil, because real GC can't be done. */)
5054 undo_list any more, we can finally mark the list. */ 5051 undo_list any more, we can finally mark the list. */
5055 mark_object (nextb->BUFFER_INTERNAL_FIELD (undo_list)); 5052 mark_object (nextb->BUFFER_INTERNAL_FIELD (undo_list));
5056 5053
5057 nextb = nextb->next; 5054 nextb = nextb->header.next.buffer;
5058 } 5055 }
5059 } 5056 }
5060 5057
@@ -5228,7 +5225,7 @@ static size_t mark_object_loop_halt;
5228static void 5225static void
5229mark_vectorlike (struct Lisp_Vector *ptr) 5226mark_vectorlike (struct Lisp_Vector *ptr)
5230{ 5227{
5231 register EMACS_UINT size = ptr->size; 5228 register EMACS_UINT size = ptr->header.size;
5232 register EMACS_UINT i; 5229 register EMACS_UINT i;
5233 5230
5234 eassert (!VECTOR_MARKED_P (ptr)); 5231 eassert (!VECTOR_MARKED_P (ptr));
@@ -5251,7 +5248,7 @@ mark_vectorlike (struct Lisp_Vector *ptr)
5251static void 5248static void
5252mark_char_table (struct Lisp_Vector *ptr) 5249mark_char_table (struct Lisp_Vector *ptr)
5253{ 5250{
5254 register EMACS_UINT size = ptr->size & PSEUDOVECTOR_SIZE_MASK; 5251 register EMACS_UINT size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK;
5255 register EMACS_UINT i; 5252 register EMACS_UINT i;
5256 5253
5257 eassert (!VECTOR_MARKED_P (ptr)); 5254 eassert (!VECTOR_MARKED_P (ptr));
@@ -5364,7 +5361,7 @@ mark_object (Lisp_Object arg)
5364 if (po != &buffer_defaults && po != &buffer_local_symbols) 5361 if (po != &buffer_defaults && po != &buffer_local_symbols)
5365 { 5362 {
5366 struct buffer *b; 5363 struct buffer *b;
5367 for (b = all_buffers; b && b != po; b = b->next) 5364 for (b = all_buffers; b && b != po; b = b->header.next)
5368 ; 5365 ;
5369 if (b == NULL) 5366 if (b == NULL)
5370 abort (); 5367 abort ();
@@ -5380,7 +5377,7 @@ mark_object (Lisp_Object arg)
5380 recursion there. */ 5377 recursion there. */
5381 { 5378 {
5382 register struct Lisp_Vector *ptr = XVECTOR (obj); 5379 register struct Lisp_Vector *ptr = XVECTOR (obj);
5383 register EMACS_UINT size = ptr->size; 5380 register EMACS_UINT size = ptr->header.size;
5384 register EMACS_UINT i; 5381 register EMACS_UINT i;
5385 5382
5386 CHECK_LIVE (live_vector_p); 5383 CHECK_LIVE (live_vector_p);
@@ -6012,10 +6009,10 @@ gc_sweep (void)
6012 if (!VECTOR_MARKED_P (buffer)) 6009 if (!VECTOR_MARKED_P (buffer))
6013 { 6010 {
6014 if (prev) 6011 if (prev)
6015 prev->next = buffer->next; 6012 prev->header.next = buffer->header.next;
6016 else 6013 else
6017 all_buffers = buffer->next; 6014 all_buffers = buffer->header.next.buffer;
6018 next = buffer->next; 6015 next = buffer->header.next.buffer;
6019 lisp_free (buffer); 6016 lisp_free (buffer);
6020 buffer = next; 6017 buffer = next;
6021 } 6018 }
@@ -6023,7 +6020,7 @@ gc_sweep (void)
6023 { 6020 {
6024 VECTOR_UNMARK (buffer); 6021 VECTOR_UNMARK (buffer);
6025 UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer)); 6022 UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer));
6026 prev = buffer, buffer = buffer->next; 6023 prev = buffer, buffer = buffer->header.next.buffer;
6027 } 6024 }
6028 } 6025 }
6029 6026
@@ -6036,10 +6033,10 @@ gc_sweep (void)
6036 if (!VECTOR_MARKED_P (vector)) 6033 if (!VECTOR_MARKED_P (vector))
6037 { 6034 {
6038 if (prev) 6035 if (prev)
6039 prev->next = vector->next; 6036 prev->header.next = vector->header.next;
6040 else 6037 else
6041 all_vectors = vector->next; 6038 all_vectors = vector->header.next.vector;
6042 next = vector->next; 6039 next = vector->header.next.vector;
6043 lisp_free (vector); 6040 lisp_free (vector);
6044 n_vectors--; 6041 n_vectors--;
6045 vector = next; 6042 vector = next;
@@ -6048,11 +6045,11 @@ gc_sweep (void)
6048 else 6045 else
6049 { 6046 {
6050 VECTOR_UNMARK (vector); 6047 VECTOR_UNMARK (vector);
6051 if (vector->size & PSEUDOVECTOR_FLAG) 6048 if (vector->header.size & PSEUDOVECTOR_FLAG)
6052 total_vector_size += (PSEUDOVECTOR_SIZE_MASK & vector->size); 6049 total_vector_size += PSEUDOVECTOR_SIZE_MASK & vector->header.size;
6053 else 6050 else
6054 total_vector_size += vector->size; 6051 total_vector_size += vector->header.size;
6055 prev = vector, vector = vector->next; 6052 prev = vector, vector = vector->header.next.vector;
6056 } 6053 }
6057 } 6054 }
6058 6055