Subject: Re: bug#8623: 23.3.50; (woman "git-remote") crashes

From: Eli Zaretskii <[email-masked]>
Date: Mon, 09 May 2011 13:13:22 +0300

> Date: Sun, 08 May 2011 22:27:45 +0300
> From: Eli Zaretskii <[email-masked]>
> Cc: [email-masked], [email-masked]
> 
> Try the one below, I tried to resolve all the conflicts.  Caveat: I
> didn't attempt to build it, so it's possible that you will need a few
> more tweaks.

For the record, the final diffs (after building and fixing some more
problems) are below:

=== modified file 'src/ChangeLog'
--- src/ChangeLog	2011-04-29 14:23:44 +0000
+++ src/ChangeLog	2011-05-09 09:53:09 +0000
@@ -1,3 +1,71 @@
+2011-05-09  Eli Zaretskii  <[email-masked]>
+
+	Backport revisions 103939.1.41..103939.1.44 (inclusive) from trunk.
+	(bug#8623)
+	The next log entry shows the actual changes by Paul Eggert.
+
+2011-05-08  Paul Eggert  <[email-masked]>
+
+	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.
+	* 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.
+
+	* 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.
+	* fns.c (vector): Remove; this old hack is no longer needed.
+	* bytecode.c (exec_byte_code): Don't use XVECTOR before CHECK_VECTOR.
+
 2011-04-29  Eli Zaretskii  <[email-masked]>
 
 	* w32heap.c (allocate_heap) [USE_LISP_UNION_TYPE || USE_LSB_TAG]:

=== modified file 'src/alloc.c'
--- src/alloc.c	2011-01-02 23:50:46 +0000
+++ src/alloc.c	2011-05-09 09:45:58 +0000
@@ -163,9 +163,9 @@ static __malloc_size_t bytes_used_when_r
 #define UNMARK_STRING(S)	((S)->size &= ~ARRAY_MARK_FLAG)
 #define STRING_MARKED_P(S)	(((S)->size & ARRAY_MARK_FLAG) != 0)
 
-#define VECTOR_MARK(V)		((V)->size |= ARRAY_MARK_FLAG)
-#define VECTOR_UNMARK(V)	((V)->size &= ~ARRAY_MARK_FLAG)
-#define VECTOR_MARKED_P(V)	(((V)->size & ARRAY_MARK_FLAG) != 0)
+#define VECTOR_MARK(V)		((V)->header.size |= ARRAY_MARK_FLAG)
+#define VECTOR_UNMARK(V)	((V)->header.size &= ~ARRAY_MARK_FLAG)
+#define VECTOR_MARKED_P(V)	(((V)->header.size & ARRAY_MARK_FLAG) != 0)
 
 /* Value is the number of bytes/chars of S, a pointer to a struct
    Lisp_String.  This must be used instead of STRING_BYTES (S) or
@@ -1151,8 +1151,9 @@ allocate_buffer ()
   struct buffer *b
     = (struct buffer *) lisp_malloc (sizeof (struct buffer),
 				     MEM_TYPE_BUFFER);
-  b->size = sizeof (struct buffer) / sizeof (EMACS_INT);
-  XSETPVECTYPE (b, PVEC_BUFFER);
+  XSETPVECTYPESIZE (b, PVEC_BUFFER,
+		    ((sizeof (struct buffer) + sizeof (EMACS_INT) - 1)
+		     / sizeof (EMACS_INT)));
   return b;
 }
 
@@ -2341,10 +2342,8 @@ LENGTH must be a number.  INIT matters o
      slot `size' of the struct Lisp_Bool_Vector.  */
   val = Fmake_vector (make_number (length_in_elts + 1), Qnil);
 
-  /* Get rid of any bits that would cause confusion.  */
-  XVECTOR (val)->size = 0;	/* No Lisp_Object to trace in there.  */
-  /* Use  XVECTOR (val) rather than `p' because p->size is not TRT. */
-  XSETPVECTYPE (XVECTOR (val), PVEC_BOOL_VECTOR);
+  /* No Lisp_Object to trace in there.  */
+  XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0);
 
   p = XBOOL_VECTOR (val);
   p->size = XFASTINT (length);
@@ -2943,7 +2942,7 @@ allocate_vectorlike (len)
   consing_since_gc += nbytes;
   vector_cells_consed += len;
 
-  p->next = all_vectors;
+  p->header.next.vector = all_vectors;
   all_vectors = p;
 
   MALLOC_UNBLOCK_INPUT;
@@ -2960,7 +2959,7 @@ allocate_vector (nslots)
      EMACS_INT nslots;
 {
   struct Lisp_Vector *v = allocate_vectorlike (nslots);
-  v->size = nslots;
+  v->header.size = nslots;
   return v;
 }
 
@@ -2976,11 +2975,10 @@ allocate_pseudovector (memlen, lisplen, 
   EMACS_INT i;
 
   /* Only the first lisplen slots will be traced normally by the GC.  */
-  v->size = lisplen;
   for (i = 0; i < lisplen; ++i)
     v->contents[i] = Qnil;
 
-  XSETPVECTYPE (v, tag);	/* Add the appropriate tag.  */
+  XSETPVECTYPESIZE (v, tag, lisplen);
   return v;
 }
 
@@ -4884,7 +4882,7 @@ make_pure_vector (len)
 
   p = (struct Lisp_Vector *) pure_alloc (size, Lisp_Vectorlike);
   XSETVECTOR (new, p);
-  XVECTOR (new)->size = len;
+  XVECTOR (new)->header.size = len;
   return new;
 }
 
@@ -4916,7 +4914,7 @@ Does not copy symbols.  Copies strings w
       register int i;
       EMACS_INT size;
 
-      size = XVECTOR (obj)->size;
+      size = XVECTOR_SIZE (obj);
       if (size & PSEUDOVECTOR_FLAG)
 	size &= PSEUDOVECTOR_SIZE_MASK;
       vec = XVECTOR (make_pure_vector (size));
@@ -5038,7 +5036,7 @@ returns nil, because real GC can't be do
 	      }
 	  }
 
-	nextb = nextb->next;
+	nextb = nextb->header.next.buffer;
       }
   }
 
@@ -5184,7 +5182,7 @@ returns nil, because real GC can't be do
 	   undo_list any more, we can finally mark the list.  */
 	mark_object (nextb->undo_list);
 
-	nextb = nextb->next;
+	nextb = nextb->header.next.buffer;
       }
   }
 
@@ -5361,7 +5359,7 @@ static void
 mark_vectorlike (ptr)
      struct Lisp_Vector *ptr;
 {
-  register EMACS_INT size = ptr->size;
+  register EMACS_UINT size = ptr->header.size;
   register int i;
 
   eassert (!VECTOR_MARKED_P (ptr));
@@ -5385,7 +5383,7 @@ static void
 mark_char_table (ptr)
      struct Lisp_Vector *ptr;
 {
-  register EMACS_INT size = ptr->size & PSEUDOVECTOR_SIZE_MASK;
+  register EMACS_UINT size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK;
   register int i;
 
   eassert (!VECTOR_MARKED_P (ptr));
@@ -5500,7 +5498,7 @@ mark_object (arg)
 	  if (po != &buffer_defaults && po != &buffer_local_symbols)
 	    {
 	      struct buffer *b;
-	      for (b = all_buffers; b && b != po; b = b->next)
+	      for (b = all_buffers; b && b != po; b = b->header.next.buffer)
 		;
 	      if (b == NULL)
 		abort ();
@@ -5516,7 +5514,7 @@ mark_object (arg)
 	   recursion there.  */
 	{
 	  register struct Lisp_Vector *ptr = XVECTOR (obj);
-	  register EMACS_INT size = ptr->size;
+	  register EMACS_UINT size = ptr->header.size;
 	  register int i;
 
 	  CHECK_LIVE (live_vector_p);
@@ -6150,10 +6148,10 @@ gc_sweep ()
       if (!VECTOR_MARKED_P (buffer))
 	{
 	  if (prev)
-	    prev->next = buffer->next;
+	    prev->header.next = buffer->header.next;
 	  else
-	    all_buffers = buffer->next;
-	  next = buffer->next;
+	    all_buffers = buffer->header.next.buffer;
+	  next = buffer->header.next.buffer;
 	  lisp_free (buffer);
 	  buffer = next;
 	}
@@ -6161,7 +6159,7 @@ gc_sweep ()
 	{
 	  VECTOR_UNMARK (buffer);
 	  UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer));
-	  prev = buffer, buffer = buffer->next;
+	  prev = buffer, buffer = buffer->header.next.buffer;
 	}
   }
 
@@ -6174,10 +6172,10 @@ gc_sweep ()
       if (!VECTOR_MARKED_P (vector))
 	{
 	  if (prev)
-	    prev->next = vector->next;
+	    prev->header.next = vector->header.next;
 	  else
-	    all_vectors = vector->next;
-	  next = vector->next;
+	    all_vectors = vector->header.next.vector;
+	  next = vector->header.next.vector;
 	  lisp_free (vector);
 	  n_vectors--;
 	  vector = next;
@@ -6186,11 +6184,11 @@ gc_sweep ()
       else
 	{
 	  VECTOR_UNMARK (vector);
-	  if (vector->size & PSEUDOVECTOR_FLAG)
-	    total_vector_size += (PSEUDOVECTOR_SIZE_MASK & vector->size);
+	  if (vector->header.size & PSEUDOVECTOR_FLAG)
+	    total_vector_size += PSEUDOVECTOR_SIZE_MASK & vector->header.size;
 	  else
-	    total_vector_size += vector->size;
-	  prev = vector, vector = vector->next;
+	    total_vector_size += vector->header.size;
+	  prev = vector, vector = vector->header.next.vector;
 	}
   }

=== modified file 'src/buffer.c'
--- src/buffer.c	2011-04-10 20:55:52 +0000
+++ src/buffer.c	2011-05-09 09:46:21 +0000
@@ -53,7 +53,7 @@ extern int errno;
 struct buffer *current_buffer;		/* the current buffer */
 
 /* First buffer in chain of all buffers (in reverse order of creation).
-   Threaded through ->next.  */
+   Threaded through ->header.next.buffer.  */
 
 struct buffer *all_buffers;
 
@@ -400,7 +400,7 @@ even if it is dead.  The return value is
   b->prevent_redisplay_optimizations_p = 1;
 
   /* Put this on the chain of all buffers including killed ones.  */
-  b->next = all_buffers;
+  b->header.next.buffer = all_buffers;
   all_buffers = b;
 
   /* An ordinary buffer normally doesn't need markers
@@ -633,7 +633,7 @@ CLONE nil means the indirect buffer's st
   b->width_table = Qnil;
 
   /* Put this on the chain of all buffers including killed ones.  */
-  b->next = all_buffers;
+  b->header.next.buffer = all_buffers;
   all_buffers = b;
 
   name = Fcopy_sequence (name);
@@ -1544,7 +1544,7 @@ with SIGHUP.  */)
 
       GCPRO1 (buffer);
 
-      for (other = all_buffers; other; other = other->next)
+      for (other = all_buffers; other; other = other->header.next.buffer)
 	/* all_buffers contains dead buffers too;
 	   don't re-kill them.  */
 	if (other->base_buffer == b && !NILP (other->name))
@@ -2214,7 +2214,7 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_
 
   { /* This is probably harder to make work.  */
     struct buffer *other;
-    for (other = all_buffers; other; other = other->next)
+    for (other = all_buffers; other; other = other->header.next.buffer)
       if (other->base_buffer == other_buffer
 	  || other->base_buffer == current_buffer)
 	error ("One of the buffers to swap has indirect buffers");
@@ -2585,7 +2585,7 @@ current buffer is cleared.  */)
 
   /* Copy this buffer's new multibyte status
      into all of its indirect buffers.  */
-  for (other = all_buffers; other; other = other->next)
+  for (other = all_buffers; other; other = other->header.next.buffer)
     if (other->base_buffer == current_buffer && !NILP (other->name))
       {
 	other->enable_multibyte_characters
@@ -4346,7 +4346,7 @@ static void
 add_overlay_mod_hooklist (functionlist, overlay)
      Lisp_Object functionlist, overlay;
 {
-  int oldsize = XVECTOR (last_overlay_modification_hooks)->size;
+  int oldsize = XVECTOR_SIZE (last_overlay_modification_hooks);
 
   if (last_overlay_modification_hooks_used == oldsize)
     last_overlay_modification_hooks = larger_vector 
@@ -5150,9 +5150,9 @@ init_buffer_once ()
   buffer_local_symbols.text = &buffer_local_symbols.own_text;
   BUF_INTERVALS (&buffer_defaults) = 0;
   BUF_INTERVALS (&buffer_local_symbols) = 0;
-  XSETPVECTYPE (&buffer_defaults, PVEC_BUFFER);
+  XSETPVECTYPESIZE (&buffer_defaults, PVEC_BUFFER, 0);
   XSETBUFFER (Vbuffer_defaults, &buffer_defaults);
-  XSETPVECTYPE (&buffer_local_symbols, PVEC_BUFFER);
+  XSETPVECTYPESIZE (&buffer_local_symbols, PVEC_BUFFER, 0);
   XSETBUFFER (Vbuffer_local_symbols, &buffer_local_symbols);
 
   /* Set up the default values of various buffer slots.  */

=== modified file 'src/buffer.h'
--- src/buffer.h	2011-03-19 16:42:53 +0000
+++ src/buffer.h	2011-05-09 09:48:57 +0000
@@ -487,14 +487,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 vectorlike_header header;
 
   /* This structure holds the coordinates of the buffer contents
      in ordinary buffers.  In indirect buffers, this is not used.  */

=== modified file 'src/bytecode.c'
--- src/bytecode.c	2011-01-02 23:50:46 +0000
+++ src/bytecode.c	2011-05-09 09:34:44 +0000
@@ -415,7 +415,7 @@ If the third argument is incorrect, Emac
   /* Lisp_Object v1, v2; */
   Lisp_Object *vectorp;
 #ifdef BYTE_CODE_SAFE
-  int const_length = XVECTOR (vector)->size;
+  int const_length;
   Lisp_Object *stacke;
 #endif
   int bytestr_length;
@@ -437,6 +437,9 @@ If the third argument is incorrect, Emac
   CHECK_VECTOR (vector);
   CHECK_NUMBER (maxdepth);
 
+#ifdef BYTE_CODE_SAFE
+  const_length = XVECTOR_SIZE (vector);
+#endif
   if (STRING_MULTIBYTE (bytestr))
     /* BYTESTR must have been produced by Emacs 20.2 or the earlier
        because they produced a raw 8-bit string for byte-code and now

=== modified file 'src/callint.c'
--- src/callint.c	2011-01-02 23:50:46 +0000
+++ src/callint.c	2011-05-09 08:56:23 +0000
@@ -313,7 +313,7 @@ invoke it.  If KEYS is omitted or nil, t
   else
     {
       CHECK_VECTOR (keys);
-      key_count = XVECTOR (keys)->size;
+      key_count = XVECTOR_SIZE (keys);
     }
 
   /* Save this now, since use of minibuffer will clobber it. */

=== modified file 'src/ccl.c'
--- src/ccl.c	2011-01-02 23:50:46 +0000
+++ src/ccl.c	2011-05-09 08:56:23 +0000
@@ -1924,7 +1924,7 @@ setup_ccl_program (ccl, ccl_prog)
       if (! VECTORP (ccl_prog))
 	return -1;
       vp = XVECTOR (ccl_prog);
-      ccl->size = vp->size;
+      ccl->size = vp->header.size;
       ccl->prog = vp->contents;
       ccl->eof_ic = XINT (vp->contents[CCL_HEADER_EOF]);
       ccl->buf_magnification = XINT (vp->contents[CCL_HEADER_BUF_MAG]);

=== modified file 'src/character.c'
--- src/character.c	2011-02-23 19:56:30 +0000
+++ src/character.c	2011-05-09 08:56:23 +0000
@@ -411,7 +411,7 @@ c_string_width (const unsigned char *str
 	{
 	  val = DISP_CHAR_VECTOR (dp, c);
 	  if (VECTORP (val))
-	    thiswidth = XVECTOR (val)->size;
+	    thiswidth = XVECTOR_SIZE (val);
 	  else
 	    thiswidth = CHAR_WIDTH (c);
 	}
@@ -503,7 +503,7 @@ lisp_string_width (string, precision, nc
 	    {
 	      val = DISP_CHAR_VECTOR (dp, c);
 	      if (VECTORP (val))
-		thiswidth = XVECTOR (val)->size;
+		thiswidth = XVECTOR_SIZE (val);
 	      else
 		thiswidth = CHAR_WIDTH (c);
 	    }

=== modified file 'src/chartab.c'
--- src/chartab.c	2011-01-02 23:50:46 +0000
+++ src/chartab.c	2011-05-09 08:56:23 +0000
@@ -152,7 +152,7 @@ copy_char_table (table)
      Lisp_Object table;
 {
   Lisp_Object copy;
-  int size = XCHAR_TABLE (table)->size & PSEUDOVECTOR_SIZE_MASK;
+  int size = XCHAR_TABLE (table)->header.size & PSEUDOVECTOR_SIZE_MASK;
   int i;
 
   copy = Fmake_vector (make_number (size), Qnil);

=== modified file 'src/coding.c'
--- src/coding.c	2011-01-02 23:50:46 +0000
+++ src/coding.c	2011-05-09 08:56:23 +0000
@@ -7339,7 +7339,7 @@ handle_composition_annotation (pos, limi
 	      components = COMPOSITION_COMPONENTS (prop);
 	      if (VECTORP (components))
 		{
-		  len = XVECTOR (components)->size;
+		  len = XVECTOR_SIZE (components);
 		  for (i = 0; i < len; i++)
 		    *buf++ = XINT (AREF (components, i));
 		}

=== modified file 'src/composite.c'
--- src/composite.c	2011-01-02 23:50:46 +0000
+++ src/composite.c	2011-05-09 08:56:23 +0000
@@ -300,7 +300,7 @@ get_composition_id (charpos, bytepos, nc
     }
   else if (VECTORP (components) || CONSP (components))
     {
-      int len = XVECTOR (key)->size;
+      EMACS_UINT len = XVECTOR_SIZE (key);
 
       /* The number of elements should be odd.  */
       if ((len % 2) == 0)
@@ -333,8 +333,8 @@ get_composition_id (charpos, bytepos, nc
 		    : COMPOSITION_WITH_RULE_ALTCHARS));
   cmp->hash_index = hash_index;
   glyph_len = (cmp->method == COMPOSITION_WITH_RULE_ALTCHARS
-	       ? (XVECTOR (key)->size + 1) / 2
-	       : XVECTOR (key)->size);
+	       ? (XVECTOR_SIZE (key) + 1) / 2
+	       : XVECTOR_SIZE (key));
   cmp->glyph_len = glyph_len;
   cmp->offsets = (short *) xmalloc (sizeof (short) * glyph_len * 2);
   cmp->font = NULL;

=== modified file 'src/data.c'
--- src/data.c	2011-01-02 23:50:46 +0000
+++ src/data.c	2011-05-09 08:56:23 +0000
@@ -1402,7 +1402,7 @@ for this variable.  */)
 	{
 	  struct buffer *b;
 
-	  for (b = all_buffers; b; b = b->next)
+	  for (b = all_buffers; b; b = b->header.next.buffer)
 	    if (!PER_BUFFER_VALUE_P (b, idx))
 	      PER_BUFFER_VALUE (b, offset) = value;
 	}
@@ -2029,9 +2029,9 @@ or a byte-code object.  IDX starts at 0.
     {
       int size = 0;
       if (VECTORP (array))
-	size = XVECTOR (array)->size;
+	size = XVECTOR_SIZE (array);
       else if (COMPILEDP (array))
-	size = XVECTOR (array)->size & PSEUDOVECTOR_SIZE_MASK;
+	size = XVECTOR_SIZE (array) & PSEUDOVECTOR_SIZE_MASK;
       else
 	wrong_type_argument (Qarrayp, array);
 
@@ -2058,7 +2058,7 @@ bool-vector.  IDX starts at 0.  */)
 
   if (VECTORP (array))
     {
-      if (idxval < 0 || idxval >= XVECTOR (array)->size)
+      if (idxval < 0 || idxval >= XVECTOR_SIZE (array))
 	args_out_of_range (array, idx);
       XVECTOR (array)->contents[idxval] = newelt;
     }

=== modified file 'src/dispnew.c'
--- src/dispnew.c	2011-01-02 23:50:46 +0000
+++ src/dispnew.c	2011-05-09 08:56:23 +0000
@@ -6729,7 +6729,7 @@ pass nil for VARIABLE.  */)
     state = frame_and_buffer_state;
 
   vecp = XVECTOR (state)->contents;
-  end = vecp + XVECTOR (state)->size;
+  end = vecp + XVECTOR_SIZE (state);
 
   FOR_EACH_FRAME (tail, frame)
     {
@@ -6780,8 +6780,8 @@ pass nil for VARIABLE.  */)
   /* Reallocate the vector if data has grown to need it,
      or if it has shrunk a lot.  */
   if (! VECTORP (state)
-      || n > XVECTOR (state)->size
-      || n + 20 < XVECTOR (state)->size / 2)
+      || n > XVECTOR_SIZE (state)
+      || n + 20 < XVECTOR_SIZE (state) / 2)
     /* Add 20 extra so we grow it less often.  */
     {
       state = Fmake_vector (make_number (n + 20), Qlambda);
@@ -6811,11 +6811,11 @@ pass nil for VARIABLE.  */)
   /* Fill up the vector with lambdas (always at least one).  */
   *vecp++ = Qlambda;
   while (vecp - XVECTOR (state)->contents
-	 < XVECTOR (state)->size)
+	 < XVECTOR_SIZE (state))
     *vecp++ = Qlambda;
   /* Make sure we didn't overflow the vector.  */
   if (vecp - XVECTOR (state)->contents
-      > XVECTOR (state)->size)
+      > XVECTOR_SIZE (state))
     abort ();
   return Qt;
 }

=== modified file 'src/disptab.h'
--- src/disptab.h	2011-01-02 23:50:46 +0000
+++ src/disptab.h	2011-05-09 08:56:23 +0000
@@ -62,7 +62,7 @@ extern Lisp_Object Vglyph_table;
 /* Return the current length of the GLYPH table,
    or 0 if the table isn't currently valid.  */
 #define GLYPH_TABLE_LENGTH  \
-  ((VECTORP (Vglyph_table)) ? XVECTOR (Vglyph_table)->size : 0)
+  ((VECTORP (Vglyph_table)) ? XVECTOR_SIZE (Vglyph_table) : 0)
 
 /* Return the current base (for indexing) of the GLYPH table,
    or 0 if the table isn't currently valid.  */

=== modified file 'src/doc.c'
--- src/doc.c	2011-01-02 23:50:46 +0000
+++ src/doc.c	2011-05-09 08:56:23 +0000
@@ -809,7 +809,7 @@ a new string, without any text propertie
 	do_remap:
 	  tem = Fwhere_is_internal (name, keymap, Qt, Qnil, Qnil);
 
-	  if (VECTORP (tem) && XVECTOR (tem)->size > 1
+	  if (VECTORP (tem) && XVECTOR_SIZE (tem) > 1
 	      && EQ (AREF (tem, 0), Qremap) && SYMBOLP (AREF (tem, 1))
 	      && follow_remap)
 	    {

=== modified file 'src/fns.c'
--- src/fns.c	2011-01-02 23:50:46 +0000
+++ src/fns.c	2011-05-09 09:22:21 +0000
@@ -27,11 +27,6 @@ along with GNU Emacs.  If not, see <http
 #include <time.h>
 #include <setjmp.h>
 
-/* Note on some machines this defines `vector' as a typedef,
-   so make sure we don't use that name in this file.  */
-#undef vector
-#define vector *****
-
 #include "lisp.h"
 #include "commands.h"
 #include "character.h"
@@ -4022,9 +4017,9 @@ copy_hash_table (h1)
   struct Lisp_Vector *next;
 
   h2 = allocate_hash_table ();
-  next = h2->vec_next;
+  next = h2->header.next.vector;
   bcopy (h1, h2, sizeof *h2);
-  h2->vec_next = next;
+  h2->header.next.vector = next;
   h2->key_and_value = Fcopy_sequence (h1->key_and_value);
   h2->hash = Fcopy_sequence (h1->hash);
   h2->next = Fcopy_sequence (h1->next);
@@ -4379,7 +4374,7 @@ sweep_weak_hash_tables ()
       marked = 0;
       for (h = weak_hash_tables; h; h = h->next_weak)
 	{
-	  if (h->size & ARRAY_MARK_FLAG)
+	  if (h->header.size & ARRAY_MARK_FLAG)
 	    marked |= sweep_weak_table (h, 0);
 	}
     }
@@ -4390,7 +4385,7 @@ sweep_weak_hash_tables ()
     {
       next = h->next_weak;
 
-      if (h->size & ARRAY_MARK_FLAG)
+      if (h->header.size & ARRAY_MARK_FLAG)
 	{
 	  /* TABLE is marked as used.  Sweep its contents.  */
 	  if (h->count > 0)
@@ -4513,7 +4508,7 @@ sxhash_bool_vector (vec)
   unsigned hash = XBOOL_VECTOR (vec)->size;
   int i, n;
 
-  n = min (SXHASH_MAX_LEN, XBOOL_VECTOR (vec)->vector_size);
+  n = min (SXHASH_MAX_LEN, XBOOL_VECTOR (vec)->header.size);
   for (i = 0; i < n; ++i)
     hash = SXHASH_COMBINE (hash, XBOOL_VECTOR (vec)->data[i]);

=== modified file 'src/font.c'
--- src/font.c	2011-02-23 01:56:49 +0000
+++ src/font.c	2011-05-09 08:56:23 +0000
@@ -269,7 +269,7 @@ font_intern_prop (str, len, force_symbol
   /* The following code is copied from the function intern (in
      lread.c), and modified to suite our purpose.  */
   obarray = Vobarray;
-  if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
+  if (!VECTORP (obarray) || XVECTOR_SIZE (obarray) == 0)
     obarray = check_obarray (obarray);
   parse_str_as_multibyte ((unsigned char *) str, len, &nchars, &nbytes);
   if (len == nchars || len != nbytes)

=== modified file 'src/font.h'
--- src/font.h	2011-01-02 23:50:46 +0000
+++ src/font.h	2011-05-09 09:48:57 +0000
@@ -247,8 +247,7 @@ extern Lisp_Object Qja, Qko;
 
 struct font_spec
 {
-  EMACS_UINT size;
-  struct Lisp_Vector *next;
+  struct vectorlike_header header;
   Lisp_Object props[FONT_SPEC_MAX];
 };
 
@@ -256,8 +255,7 @@ struct font_spec
 
 struct font_entity
 {
-  EMACS_UINT size;
-  struct Lisp_Vector *next;
+  struct vectorlike_header header;
   Lisp_Object props[FONT_ENTITY_MAX];
 };
 
@@ -270,8 +268,7 @@ struct font_entity
 
 struct font
 {
-  EMACS_UINT size;
-  struct Lisp_Vector *next;
+  struct vectorlike_header header;
 
   /* All Lisp_Object components must come first.
      That ensures they are all aligned normally.  */

=== modified file 'src/frame.h'
--- src/frame.h	2011-01-02 23:50:46 +0000
+++ src/frame.h	2011-05-09 09:48:57 +0000
@@ -93,8 +93,7 @@ struct font_driver_list;
 
 struct frame
 {
-  EMACS_UINT size;
-  struct Lisp_Vector *next;
+  struct vectorlike_header header;
 
   /* All Lisp_Object components must come first.
      That ensures they are all aligned normally.  */

=== modified file 'src/fringe.c'
--- src/fringe.c	2011-03-11 03:56:20 +0000
+++ src/fringe.c	2011-05-09 08:56:23 +0000
@@ -1569,7 +1569,7 @@ If BITMAP already exists, the existing d
   if (STRINGP (bits))
     h = SCHARS (bits);
   else if (VECTORP (bits))
-    h = XVECTOR (bits)->size;
+    h = XVECTOR_SIZE (bits);
   else
     wrong_type_argument (Qsequencep, bits);

=== modified file 'src/image.c'
--- src/image.c	2011-01-29 23:56:33 +0000
+++ src/image.c	2011-05-09 08:56:23 +0000
@@ -2459,7 +2459,7 @@ xbm_image_p (object)
 	  int i;
 
 	  /* Number of elements of the vector must be >= height.  */
-	  if (XVECTOR (data)->size < height)
+	  if (XVECTOR_SIZE (data) < height)
 	    return 0;
 
 	  /* Each string or bool-vector in data must be large enough
@@ -8083,7 +8083,7 @@ gs_image_p (object)
     }
   else if (VECTORP (tem))
     {
-      if (XVECTOR (tem)->size != 4)
+      if (XVECTOR_SIZE (tem) != 4)
 	return 0;
       for (i = 0; i < 4; ++i)
 	if (!INTEGERP (XVECTOR (tem)->contents[i]))

=== modified file 'src/indent.c'
--- src/indent.c	2011-01-02 23:50:46 +0000
+++ src/indent.c	2011-05-09 09:06:22 +0000
@@ -101,7 +101,7 @@ character_width (c, dp)
   /* Everything can be handled by the display table, if it's
      present and the element is right.  */
   if (dp && (elt = DISP_CHAR_VECTOR (dp, c), VECTORP (elt)))
-    return XVECTOR (elt)->size;
+    return XVECTOR_SIZE (elt);
 
   /* Some characters are special.  */
   if (c == '\n' || c == '\t' || c == '\015')
@@ -131,7 +131,7 @@ disptab_matches_widthtab (disptab, width
 {
   int i;
 
-  if (widthtab->size != 256)
+  if (widthtab->header.size != 256)
     abort ();
 
   for (i = 0; i < 256; i++)
@@ -155,7 +155,7 @@ recompute_width_table (buf, disptab)
   if (!VECTORP (buf->width_table))
     buf->width_table = Fmake_vector (make_number (256), make_number (0));
   widthtab = XVECTOR (buf->width_table);
-  if (widthtab->size != 256)
+  if (widthtab->header.size != 256)
     abort ();
 
   for (i = 0; i < 256; i++)
@@ -301,7 +301,7 @@ skip_invisible (pos, next_boundary_p, to
     else								\
       {									\
 	if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))		\
-	  width = XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;		\
+	  width = XVECTOR_SIZE (DISP_CHAR_VECTOR (dp, c));		\
 	else								\
 	  width = CHAR_WIDTH (c);					\
 	if (width > 1)							\
@@ -786,7 +786,7 @@ string_display_width (string, beg, end)
 
       c = *--ptr;
       if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
-	col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
+	col += XVECTOR_SIZE (DISP_CHAR_VECTOR (dp, c));
       else if (c >= 040 && c < 0177)
 	col++;
       else if (c == '\n')
@@ -1159,7 +1159,7 @@ compute_motion (from, fromvpos, fromhpos
        : !NILP (current_buffer->selective_display) ? -1 : 0);
   int selective_rlen
     = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp))
-       ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : 0);
+       ? XVECTOR_SIZE (DISP_INVIS_VECTOR (dp)) : 0);
   /* The next location where the `invisible' property changes, or an
      overlay starts or ends.  */
   EMACS_INT next_boundary = from;

=== modified file 'src/keyboard.c'
--- src/keyboard.c	2011-01-02 23:50:46 +0000
+++ src/keyboard.c	2011-05-09 08:59:30 +0000
@@ -137,7 +137,7 @@ int raw_keybuf_count;
 Lisp_Object Vthis_command_keys_shift_translated;
 
 #define GROW_RAW_KEYBUF							\
- if (raw_keybuf_count == XVECTOR (raw_keybuf)->size)			\
+ if (raw_keybuf_count == XVECTOR_SIZE (raw_keybuf))			\
    raw_keybuf = larger_vector (raw_keybuf, raw_keybuf_count * 2, Qnil)  \
 
 /* Number of elements of this_command_keys
@@ -1774,7 +1774,7 @@ command_loop_1 ()
 		  if (PT == last_point_position + 1
 		      && (dp
 			  ? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
-			     ? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1
+			     ? XVECTOR_SIZE (DISP_CHAR_VECTOR (dp, lose)) == 1
 			     : (NILP (DISP_CHAR_VECTOR (dp, lose))
 				&& (lose >= 0x20 && lose < 0x7f)))
 			  : (lose >= 0x20 && lose < 0x7f))
@@ -1814,7 +1814,7 @@ command_loop_1 ()
 		  if (PT == last_point_position - 1
 		      && (dp
 			  ? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
-			     ? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1
+			     ? XVECTOR_SIZE (DISP_CHAR_VECTOR (dp, lose)) == 1
 			     : (NILP (DISP_CHAR_VECTOR (dp, lose))
 				&& (lose >= 0x20 && lose < 0x7f)))
 			  : (lose >= 0x20 && lose < 0x7f))
@@ -3203,7 +3203,7 @@ read_char (commandflag, nmaps, maps, pre
       if ((STRINGP (current_kboard->Vkeyboard_translate_table)
 	   && SCHARS (current_kboard->Vkeyboard_translate_table) > (unsigned) XFASTINT (c))
 	  || (VECTORP (current_kboard->Vkeyboard_translate_table)
-	      && XVECTOR (current_kboard->Vkeyboard_translate_table)->size > (unsigned) XFASTINT (c))
+	      && XVECTOR_SIZE (current_kboard->Vkeyboard_translate_table) > (unsigned) XFASTINT (c))
 	  || (CHAR_TABLE_P (current_kboard->Vkeyboard_translate_table)
 	      && CHARACTERP (c)))
 	{
@@ -4552,7 +4552,7 @@ timer_start_idle ()
 
       timer = XCAR (timers);
 
-      if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
+      if (!VECTORP (timer) || XVECTOR_SIZE (timer) != 8)
 	continue;
       XVECTOR (timer)->contents[0] = Qnil;
     }
@@ -4646,7 +4646,7 @@ timer_check_2 ()
       if (!NILP (timers))
 	{
 	  timer = XCAR (timers);
-	  if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
+	  if (!VECTORP (timer) || XVECTOR_SIZE (timer) != 8)
 	    {
 	      timers = XCDR (timers);
 	      continue;
@@ -4664,7 +4664,7 @@ timer_check_2 ()
       if (!NILP (idle_timers))
 	{
 	  timer = XCAR (idle_timers);
-	  if (!VECTORP (timer) || XVECTOR (timer)->size != 8)
+	  if (!VECTORP (timer) || XVECTOR_SIZE (timer) != 8)
 	    {
 	      idle_timers = XCDR (idle_timers);
 	      continue;
@@ -5830,7 +5830,7 @@ make_lispy_event (event)
 		/* Find the menu bar item under `column'.  */
 		item = Qnil;
 		items = FRAME_MENU_BAR_ITEMS (f);
-		for (i = 0; i < XVECTOR (items)->size; i += 4)
+		for (i = 0; i < XVECTOR_SIZE (items); i += 4)
 		  {
 		    Lisp_Object pos, string;
 		    string = AREF (items, i + 1);
@@ -6025,7 +6025,7 @@ make_lispy_event (event)
 				      Qmouse_click, Vlispy_mouse_stem,
 				      NULL,
 				      &mouse_syms,
-				      XVECTOR (mouse_syms)->size);
+				      XVECTOR_SIZE (mouse_syms));
 	  if (event->modifiers & drag_modifier)
 	    return Fcons (head,
 			  Fcons (start_pos,
@@ -6198,7 +6198,7 @@ make_lispy_event (event)
 				    Qmouse_click,
 				    Vlispy_mouse_stem,
 				    NULL, &mouse_syms,
-				    XVECTOR (mouse_syms)->size);
+				    XVECTOR_SIZE (mouse_syms));
 	return Fcons (head, Fcons (position, Qnil));
       }
 
@@ -6318,7 +6318,7 @@ make_lispy_event (event)
 				    Qmouse_click, Vlispy_mouse_stem,
 				    NULL,
 				    &mouse_syms,
-				    XVECTOR (mouse_syms)->size);
+				    XVECTOR_SIZE (mouse_syms));
 
 	if (event->modifiers & drag_modifier)
 	  return Fcons (head,
@@ -6825,7 +6825,7 @@ modify_event_symbol (symbol_num, modifie
   else
     {
       if (! VECTORP (*symbol_table)
-	  || XVECTOR (*symbol_table)->size != table_size)
+	  || XVECTOR_SIZE (*symbol_table) != table_size)
 	{
 	  Lisp_Object size;
 
@@ -7865,7 +7865,7 @@ menu_bar_items (old)
 
   /* Add nil, nil, nil, nil at the end.  */
   i = menu_bar_items_index;
-  if (i + 4 > XVECTOR (menu_bar_items_vector)->size)
+  if (i + 4 > XVECTOR_SIZE (menu_bar_items_vector))
     menu_bar_items_vector = larger_vector (menu_bar_items_vector, 2 * i, Qnil);
   /* Add this item.  */
   XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
@@ -7937,7 +7937,7 @@ menu_bar_item (key, item, dummy1, dummy2
   if (i == menu_bar_items_index)
     {
       /* If vector is too small, get a bigger one.  */
-      if (i + 4 > XVECTOR (menu_bar_items_vector)->size)
+      if (i + 4 > XVECTOR_SIZE (menu_bar_items_vector))
 	menu_bar_items_vector = larger_vector (menu_bar_items_vector, 2 * i, Qnil);
       /* Add this item.  */
       XVECTOR (menu_bar_items_vector)->contents[i++] = key;
@@ -8573,7 +8573,7 @@ parse_tool_bar_item (key, item)
 	}
       else if (EQ (key, QCimage)
 	       && (CONSP (value)
-		   || (VECTORP (value) && XVECTOR (value)->size == 4)))
+		   || (VECTORP (value) && XVECTOR_SIZE (value) == 4)))
 	/* Value is either a single image specification or a vector
 	   of 4 such specifications for the different button states.  */
 	PROP (TOOL_BAR_ITEM_IMAGES) = value;
@@ -8634,10 +8634,10 @@ append_tool_bar_item ()
 
   /* Enlarge tool_bar_items_vector if necessary.  */
   if (ntool_bar_items + TOOL_BAR_ITEM_NSLOTS
-      >= XVECTOR (tool_bar_items_vector)->size)
+      >= XVECTOR_SIZE (tool_bar_items_vector))
     tool_bar_items_vector
       = larger_vector (tool_bar_items_vector,
-		       2 * XVECTOR (tool_bar_items_vector)->size, Qnil);
+		       2 * XVECTOR_SIZE (tool_bar_items_vector), Qnil);
 
   /* Append entries from tool_bar_item_properties to the end of
      tool_bar_items_vector.  */
@@ -8966,7 +8966,7 @@ read_char_minibuf_menu_prompt (commandfl
 		}
 
 	      /* Move past this element.  */
-	      if (idx >= 0 && idx + 1 >= XVECTOR (vector)->size)
+	      if (idx >= 0 && idx + 1 >= XVECTOR_SIZE (vector))
 		/* Handle reaching end of dense table.  */
 		idx = -1;
 	      if (idx >= 0)
@@ -10244,7 +10244,7 @@ read_key_sequence (keybuf, bufsize, prom
 	      /* Treat uppercase keys as shifted.  */
 	      || (INTEGERP (key)
 		  && (KEY_TO_CHAR (key)
-		      < XCHAR_TABLE (current_buffer->downcase_table)->size)
+		      < XCHAR_TABLE (current_buffer->downcase_table)->header.size)
 		  && UPPERCASEP (KEY_TO_CHAR (key))))
 	    {
 	      Lisp_Object new_key
@@ -10642,7 +10642,7 @@ give to the command you invoke, if it as
     this_single_command_key_start = 0;
 
     keys = XVECTOR (saved_keys)->contents;
-    for (i = 0; i < XVECTOR (saved_keys)->size; i++)
+    for (i = 0; i < XVECTOR_SIZE (saved_keys); i++)
       add_command_key (keys[i]);
 
     for (i = 0; i < SCHARS (function); i++)
@@ -10939,7 +10939,7 @@ KEEP-RECORD is non-nil.  */)
 
   if (NILP (keep_record))
     {
-      for (i = 0; i < XVECTOR (recent_keys)->size; ++i)
+      for (i = 0; i < XVECTOR_SIZE (recent_keys); ++i)
 	XVECTOR (recent_keys)->contents[i] = Qnil;
       total_keys = 0;
       recent_keys_index = 0;

=== modified file 'src/keymap.c'
--- src/keymap.c	2011-02-23 04:26:42 +0000
+++ src/keymap.c	2011-05-09 09:01:52 +0000
@@ -421,7 +421,7 @@ Return PARENT.  PARENT should be nil or 
 				XCDR (XCAR (list)));
 
       if (VECTORP (XCAR (list)))
-	for (i = 0; i < XVECTOR (XCAR (list))->size; i++)
+	for (i = 0; i < XVECTOR_SIZE (XCAR (list)); i++)
 	  if (CONSP (XVECTOR (XCAR (list))->contents[i]))
 	    fix_submap_inheritance (keymap, make_number (i),
 				    XVECTOR (XCAR (list))->contents[i]);
@@ -2337,7 +2337,7 @@ spaces are put between sequence elements
   if (STRINGP (list))
     size = SCHARS (list);
   else if (VECTORP (list))
-    size = XVECTOR (list)->size;
+    size = XVECTOR_SIZE (list);
   else if (CONSP (list))
     size = XINT (Flength (list));
   else
@@ -3257,7 +3257,7 @@ key             binding\n\
 
 	  elt = XCAR (list);
 	  prefix = Fcar (elt);
-	  if (XVECTOR (prefix)->size >= 1)
+	  if (XVECTOR_SIZE (prefix) >= 1)
 	    {
 	      tem = Faref (prefix, make_number (0));
 	      if (EQ (tem, Qmenu_bar))
@@ -3300,7 +3300,7 @@ key             binding\n\
 	  /* If the sequence by which we reach this keymap is zero-length,
 	     then the shadow map for this keymap is just SHADOW.  */
 	  if ((STRINGP (prefix) && SCHARS (prefix) == 0)
-	      || (VECTORP (prefix) && XVECTOR (prefix)->size == 0))
+	      || (VECTORP (prefix) && XVECTOR_SIZE (prefix) == 0))
 	    ;
 	  /* If the sequence by which we reach this keymap actually has
 	     some elements, then the sequence's definition in SHADOW is
@@ -3748,7 +3748,7 @@ describe_vector (vector, prefix, args, e
   if (CHAR_TABLE_P (vector))
     stop = MAX_5_BYTE_CHAR + 1, to = MAX_CHAR + 1;
   else
-    stop = to = XVECTOR (vector)->size;
+    stop = to = XVECTOR_SIZE (vector);
 
   for (i = from; ; i++)
     {

=== modified file 'src/lisp.h'
--- src/lisp.h	2011-01-23 22:38:13 +0000
+++ src/lisp.h	2011-05-09 09:48:57 +0000
@@ -550,6 +550,12 @@ extern Lisp_Object make_number P_ ((EMAC
 #define XSYMBOL(a) (eassert (SYMBOLP(a)),(struct Lisp_Symbol *) XPNTR(a))
 #define XFLOAT(a) (eassert (FLOATP(a)),(struct Lisp_Float *) XPNTR(a))
 
+/* Extract the size field of a vector or vector-like object.  */
+
+#define XVECTOR_SIZE(a) (XVECTOR (a)->header.size + 0)
+#define XVECTORLIKE_HEADER_SIZE(a) \
+  (((struct vectorlike_header *) XPNTR (a))->size + 0)
+
 /* Misc types.  */
 
 #define XMISC(a)   ((union Lisp_Misc *) XPNTR(a))
@@ -595,17 +601,24 @@ extern Lisp_Object make_number P_ ((EMAC
 
 /* Pseudovector types.  */
 
-#define XSETPVECTYPE(v,code) ((v)->size |= PSEUDOVECTOR_FLAG | (code))
+#define XSETPVECTYPE(v, code) XSETTYPED_PVECTYPE(v, header.size, code)
+#define XSETTYPED_PVECTYPE(v, size_member, code) \
+  ((v)->size_member |= PSEUDOVECTOR_FLAG | (code))
+#define XSETPVECTYPESIZE(v, code, sizeval) \
+  ((v)->header.size = PSEUDOVECTOR_FLAG | (code) | (sizeval))
 #define XSETPSEUDOVECTOR(a, b, code) \
+  XSETTYPED_PSEUDOVECTOR(a, b, XVECTORLIKE_HEADER_SIZE (a), code)
+#define XSETTYPED_PSEUDOVECTOR(a, b, size, code)			\
   (XSETVECTOR (a, b),							\
-   eassert ((XVECTOR (a)->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))	\
+   eassert ((size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))		\
 	    == (PSEUDOVECTOR_FLAG | (code))))
 #define XSETWINDOW_CONFIGURATION(a, b) \
   (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION))
 #define XSETPROCESS(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_PROCESS))
 #define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW))
 #define XSETTERMINAL(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL))
-#define XSETSUBR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUBR))
+#define XSETSUBR(a, b) \
+  XSETTYPED_PSEUDOVECTOR (a, b, XSUBR (a)->size, PVEC_SUBR)
 #define XSETCOMPILED(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_COMPILED))
 #define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER))
 #define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE))
@@ -615,7 +628,7 @@ extern Lisp_Object make_number P_ ((EMAC
 /* Convenience macros for dealing with Lisp arrays.  */
 
 #define AREF(ARRAY, IDX)	XVECTOR ((ARRAY))->contents[IDX]
-#define ASIZE(ARRAY)		XVECTOR ((ARRAY))->size
+#define ASIZE(ARRAY)		XVECTOR_SIZE (ARRAY)
 /* The IDX==IDX tries to detect when the macro argument is side-effecting.  */
 #define ASET(ARRAY, IDX, VAL)	\
   (eassert ((IDX) == (IDX)),				\
@@ -780,11 +793,21 @@ struct Lisp_String
 #define OFFSETOF(type,field) \
   ((int)((char*)&((type*)0)->field - (char*)0))
 #endif
+/* Header of vector-like objects.  This type documents the constraints on
+   layout of vectors and pseudovectors, and helps optimizing compilers not get
+   fooled by Emacs's type punning.  */
+struct vectorlike_header
+  {
+    EMACS_UINT size;
+    union {
+      struct buffer *buffer;
+      struct Lisp_Vector *vector;
+    } next;
+  };
 
 struct Lisp_Vector
   {
-    EMACS_UINT size;
-    struct Lisp_Vector *next;
+    struct vectorlike_header header;
     Lisp_Object contents[1];
   };
 
@@ -820,7 +843,7 @@ struct Lisp_Vector
 /* Return the number of "extra" slots in the char table CT.  */
 
 #define CHAR_TABLE_EXTRA_SLOTS(CT)	\
-  (((CT)->size & PSEUDOVECTOR_SIZE_MASK) - CHAR_TABLE_STANDARD_SLOTS)
+  (((CT)->header.size & PSEUDOVECTOR_SIZE_MASK) - CHAR_TABLE_STANDARD_SLOTS)
 
 #ifdef __GNUC__
 
@@ -882,12 +905,11 @@ struct Lisp_Sub_Char_Table;
 
 struct Lisp_Char_Table
   {
-    /* This is the vector's size field, which also holds the
+    /* HEADER.SIZE is the vector's size field, which also holds the
        pseudovector type information.  It holds the size, too.
        The size counts the defalt, parent, purpose, ascii,
        contents, and extras slots.  */
-    EMACS_UINT size;
-    struct Lisp_Vector *next;
+    struct vectorlike_header header;
 
     /* This holds a default value,
        which is used whenever the value for a specific character is nil.  */
@@ -914,10 +936,9 @@ struct Lisp_Char_Table
 
 struct Lisp_Sub_Char_Table
   {
-    /* This is the vector's size field, which also holds the
+    /* HEADER.SIZE is the vector's size field, which also holds the
        pseudovector type information.  It holds the size, too.  */
-    EMACS_INT size;
-    struct Lisp_Vector *next;
+    struct vectorlike_header header;
 
     /* Depth of this sub char-table.  It should be 1, 2, or 3.  A sub
        char-table of depth 1 contains 16 elements, and each element
@@ -936,10 +957,9 @@ struct Lisp_Sub_Char_Table
 /* A boolvector is a kind of vectorlike, with contents are like a string.  */
 struct Lisp_Bool_Vector
   {
-    /* This is the vector's size field.  It doesn't have the real size,
+    /* HEADER.SIZE is the vector's size field.  It doesn't have the real size,
        just the subtype information.  */
-    EMACS_UINT vector_size;
-    struct Lisp_Vector *next;
+    struct vectorlike_header header;
     /* This is the size in bits.  */
     EMACS_UINT size;
     /* This contains the actual bits, packed into bytes.  */
@@ -952,7 +972,7 @@ struct Lisp_Bool_Vector
 
    This type is treated in most respects as a pseudovector,
    but since we never dynamically allocate or free them,
-   we don't need a next-vector field.  */
+   we don't need a struct vectorlike_header and its 'next' field.  */
 
 struct Lisp_Subr
   {
@@ -1066,9 +1086,8 @@ struct Lisp_Symbol
 
 struct Lisp_Hash_Table
 {
-  /* Vector fields.  The hash table code doesn't refer to these.  */
-  EMACS_UINT size;
-  struct Lisp_Vector *vec_next;
+  /* This is for Lisp; the hash table code does not refer to it.  */
+  struct vectorlike_header header;
 
   /* Function used to compare keys.  */
   Lisp_Object test;
@@ -1169,7 +1188,7 @@ struct Lisp_Hash_Table
 
 /* Value is the size of hash table H.  */
 
-#define HASH_TABLE_SIZE(H) XVECTOR ((H)->next)->size
+#define HASH_TABLE_SIZE(H) XVECTOR_SIZE ((H)->next)
 
 /* Default size for hash tables if not specified.  */
 
@@ -1551,7 +1570,7 @@ typedef struct {
 #define CONSP(x) (XTYPE ((x)) == Lisp_Cons)
 
 #define FLOATP(x) (XTYPE ((x)) == Lisp_Float)
-#define VECTORP(x)    (VECTORLIKEP (x) && !(XVECTOR (x)->size & PSEUDOVECTOR_FLAG))
+#define VECTORP(x)    (VECTORLIKEP (x) && !(XVECTOR_SIZE (x) & PSEUDOVECTOR_FLAG))
 #define OVERLAYP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay)
 #define MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
 #define INTFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Intfwd)
@@ -1566,8 +1585,14 @@ typedef struct {
 
 /* True if object X is a pseudovector whose code is CODE.  */
 #define PSEUDOVECTORP(x, code)					\
+  TYPED_PSEUDOVECTORP(x, vectorlike_header, code)
+
+/* True if object X, with internal type struct T *, is a pseudovector whose
+   code is CODE.  */
+#define TYPED_PSEUDOVECTORP(x, t, code)				\
   (VECTORLIKEP (x)						\
-   && (((XVECTOR (x)->size & (PSEUDOVECTOR_FLAG | (code))))	\
+   && (((((struct t *) XPNTR (x))->size				\
+	 & (PSEUDOVECTOR_FLAG | (code))))			\
        == (PSEUDOVECTOR_FLAG | (code))))
 
 /* Test for specific pseudovector types.  */
@@ -1575,7 +1600,7 @@ typedef struct {
 #define PROCESSP(x) PSEUDOVECTORP (x, PVEC_PROCESS)
 #define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW)
 #define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL)
-#define SUBRP(x) PSEUDOVECTORP (x, PVEC_SUBR)
+#define SUBRP(x) TYPED_PSEUDOVECTORP (x, Lisp_Subr, PVEC_SUBR)
 #define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED)
 #define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER)
 #define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE)

=== modified file 'src/lread.c'
--- src/lread.c	2011-03-19 16:42:53 +0000
+++ src/lread.c	2011-05-09 08:56:23 +0000
@@ -2433,7 +2433,7 @@ read1 (readcharfun, pch, first_in_list)
 	    {
 	      Lisp_Object tmp;
 	      tmp = read_vector (readcharfun, 0);
-	      if (XVECTOR (tmp)->size < CHAR_TABLE_STANDARD_SLOTS)
+	      if (XVECTOR_SIZE (tmp) < CHAR_TABLE_STANDARD_SLOTS)
 		error ("Invalid size char-table");
 	      XSETPVECTYPE (XVECTOR (tmp), PVEC_CHAR_TABLE);
 	      return tmp;
@@ -2452,7 +2452,7 @@ read1 (readcharfun, pch, first_in_list)
 		  depth = XINT (AREF (tmp, 0));
 		  if (depth < 1 || depth > 3)
 		    error ("Invalid depth in char-table");
-		  size = XVECTOR (tmp)->size - 2;
+		  size = XVECTOR_SIZE (tmp) - 2;
 		  if (chartab_size [depth] != size)
 		    error ("Invalid size char-table");
 		  XSETPVECTYPE (XVECTOR (tmp), PVEC_SUB_CHAR_TABLE);
@@ -2503,7 +2503,7 @@ read1 (readcharfun, pch, first_in_list)
 	     build them using function calls.  */
 	  Lisp_Object tmp;
 	  tmp = read_vector (readcharfun, 1);
-	  return Fmake_byte_code (XVECTOR (tmp)->size,
+	  return Fmake_byte_code (XVECTOR_SIZE (tmp),
 				  XVECTOR (tmp)->contents);
 	}
       if (c == '(')
@@ -3332,7 +3332,7 @@ read_vector (readcharfun, bytecodeflag)
   len = Flength (tem);
   vector = (read_pure ? make_pure_vector (XINT (len)) : Fmake_vector (len, Qnil));
 
-  size = XVECTOR (vector)->size;
+  size = XVECTOR_SIZE (vector);
   ptr = XVECTOR (vector)->contents;
   for (i = 0; i < size; i++)
     {
@@ -3601,7 +3601,7 @@ Lisp_Object
 check_obarray (obarray)
      Lisp_Object obarray;
 {
-  if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
+  if (!VECTORP (obarray) || XVECTOR_SIZE (obarray) == 0)
     {
       /* If Vobarray is now invalid, force it to be valid.  */
       if (EQ (Vobarray, obarray)) Vobarray = initial_obarray;
@@ -3622,7 +3622,7 @@ intern (str)
   Lisp_Object obarray;
 
   obarray = Vobarray;
-  if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
+  if (!VECTORP (obarray) || XVECTOR_SIZE (obarray) == 0)
     obarray = check_obarray (obarray);
   tem = oblookup (obarray, str, len, len);
   if (SYMBOLP (tem))
@@ -3638,7 +3638,7 @@ intern_c_string (const char *str)
   Lisp_Object obarray;
 
   obarray = Vobarray;
-  if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
+  if (!VECTORP (obarray) || XVECTOR_SIZE (obarray) == 0)
     obarray = check_obarray (obarray);
   tem = oblookup (obarray, str, len, len);
   if (SYMBOLP (tem))
@@ -3831,10 +3831,10 @@ oblookup (obarray, ptr, size, size_byte)
   Lisp_Object bucket, tem;
 
   if (!VECTORP (obarray)
-      || (obsize = XVECTOR (obarray)->size) == 0)
+      || (obsize = XVECTOR_SIZE (obarray)) == 0)
     {
       obarray = check_obarray (obarray);
-      obsize = XVECTOR (obarray)->size;
+      obsize = XVECTOR_SIZE (obarray);
     }
   /* This is sometimes needed in the middle of GC.  */
   obsize &= ~ARRAY_MARK_FLAG;
@@ -3887,7 +3887,7 @@ map_obarray (obarray, fn, arg)
   register int i;
   register Lisp_Object tail;
   CHECK_VECTOR (obarray);
-  for (i = XVECTOR (obarray)->size - 1; i >= 0; i--)
+  for (i = XVECTOR_SIZE (obarray) - 1; i >= 0; i--)
     {
       tail = XVECTOR (obarray)->contents[i];
       if (SYMBOLP (tail))
@@ -3974,7 +3974,7 @@ defsubr (sname)
 {
   Lisp_Object sym;
   sym = intern_c_string (sname->symbol_name);
-  XSETPVECTYPE (sname, PVEC_SUBR);
+  XSETTYPED_PVECTYPE (sname, size, PVEC_SUBR);
   XSETSUBR (XSYMBOL (sym)->function, sname);
 }

=== modified file 'src/minibuf.c'
--- src/minibuf.c	2011-01-02 23:50:46 +0000
+++ src/minibuf.c	2011-05-09 08:56:23 +0000
@@ -1326,7 +1326,7 @@ is used to further constrain the set of 
   if (type == obarray_table)
     {
       collection = check_obarray (collection);
-      obsize = XVECTOR (collection)->size;
+      obsize = XVECTOR_SIZE (collection);
       bucket = XVECTOR (collection)->contents[index];
     }
 
@@ -1590,7 +1590,7 @@ with a space are ignored unless STRING i
   if (type == 2)
     {
       collection = check_obarray (collection);
-      obsize = XVECTOR (collection)->size;
+      obsize = XVECTOR_SIZE (collection);
       bucket = XVECTOR (collection)->contents[index];
     }
 
@@ -1889,7 +1889,7 @@ the values STRING, PREDICATE and `lambda
 
       if (completion_ignore_case && !SYMBOLP (tem))
 	{
-	  for (i = XVECTOR (collection)->size - 1; i >= 0; i--)
+	  for (i = XVECTOR_SIZE (collection) - 1; i >= 0; i--)
 	    {
 	      tail = XVECTOR (collection)->contents[i];
 	      if (SYMBOLP (tail))

=== modified file 'src/print.c'
--- src/print.c	2011-01-02 23:50:46 +0000
+++ src/print.c	2011-05-09 09:25:50 +0000
@@ -1365,7 +1365,7 @@ print_preprocess (obj)
 	      /* Initialize the table.  */
 	      Vprint_number_table = Fmake_vector (make_number (40), Qnil);
 	    }
-	  else if (XVECTOR (Vprint_number_table)->size == print_number_index * 2)
+	  else if (XVECTOR_SIZE (Vprint_number_table) == print_number_index * 2)
 	    {
 	      /* Reallocate the table.  */
 	      int i = print_number_index * 4;
@@ -1411,7 +1411,7 @@ print_preprocess (obj)
 	  goto loop;
 
 	case Lisp_Vectorlike:
-	  size = XVECTOR (obj)->size;
+	  size = XVECTOR_SIZE (obj);
 	  if (size & PSEUDOVECTOR_FLAG)
 	    size &= PSEUDOVECTOR_SIZE_MASK;
 	  for (i = 0; i < size; i++)
@@ -2051,7 +2051,7 @@ print_object (obj, printcharfun, escapef
 	      strout (SDATA (SYMBOL_NAME (h->weak)), -1, -1, printcharfun, 0);
 	      PRINTCHAR (' ');
 	      sprintf (buf, "%ld/%ld", (long) h->count,
-		       (long) XVECTOR (h->next)->size);
+		       (long) XVECTOR_SIZE (h->next));
 	      strout (buf, -1, -1, printcharfun, 0);
 	    }
 	  sprintf (buf, " 0x%lx", (unsigned long) h);
@@ -2062,7 +2062,7 @@ print_object (obj, printcharfun, escapef
 	    #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
 	  /* Always print the size. */
 	  sprintf (buf, "#s(hash-table size %ld",
-		   (long) XVECTOR (h->next)->size);
+		   (long) XVECTOR_SIZE (h->next));
 	  strout (buf, -1, -1, printcharfun, 0);
 
 	  if (!NILP (h->test))
@@ -2174,7 +2174,7 @@ print_object (obj, printcharfun, escapef
 	}
       else
 	{
-	  EMACS_INT size = XVECTOR (obj)->size;
+	  EMACS_INT size = XVECTOR_SIZE (obj);
 	  if (COMPILEDP (obj))
 	    {
 	      PRINTCHAR ('#');
@@ -2354,7 +2354,7 @@ print_object (obj, printcharfun, escapef
 	if (MISCP (obj))
 	  sprintf (buf, "(MISC 0x%04x)", (int) XMISCTYPE (obj));
 	else if (VECTORLIKEP (obj))
-	  sprintf (buf, "(PVEC 0x%08x)", (int) XVECTOR (obj)->size);
+	  sprintf (buf, "(PVEC 0x%08lx)", (unsigned long) XVECTOR_SIZE (obj));
 	else
 	  sprintf (buf, "(0x%02x)", (int) XTYPE (obj));
 	strout (buf, -1, -1, printcharfun, 0);

=== modified file 'src/process.c'
--- src/process.c	2011-03-19 18:47:17 +0000
+++ src/process.c	2011-05-09 08:56:23 +0000
@@ -1277,25 +1277,26 @@ Returns nil if format of ADDRESS is inva
   if (VECTORP (address))  /* AF_INET or AF_INET6 */
     {
       register struct Lisp_Vector *p = XVECTOR (address);
+      EMACS_UINT size = p->header.size;
       Lisp_Object args[10];
       int nargs, i;
 
-      if (p->size == 4 || (p->size == 5 && !NILP (omit_port)))
+      if (size == 4 || (size == 5 && !NILP (omit_port)))
 	{
 	  args[0] = build_string ("%d.%d.%d.%d");
 	  nargs = 4;
 	}
-      else if (p->size == 5)
+      else if (size == 5)
 	{
 	  args[0] = build_string ("%d.%d.%d.%d:%d");
 	  nargs = 5;
 	}
-      else if (p->size == 8 || (p->size == 9 && !NILP (omit_port)))
+      else if (size == 8 || (size == 9 && !NILP (omit_port)))
 	{
 	  args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x");
 	  nargs = 8;
 	}
-      else if (p->size == 9)
+      else if (size == 9)
 	{
 	  args[0] = build_string ("[%x:%x:%x:%x:%x:%x:%x:%x]:%d");
 	  nargs = 9;
@@ -2477,13 +2478,13 @@ get_lisp_to_sockaddr_size (address, fami
   if (VECTORP (address))
     {
       p = XVECTOR (address);
-      if (p->size == 5)
+      if (p->header.size == 5)
 	{
 	  *familyp = AF_INET;
 	  return sizeof (struct sockaddr_in);
 	}
 #ifdef AF_INET6
-      else if (p->size == 9)
+      else if (p->header.size == 9)
 	{
 	  *familyp = AF_INET6;
 	  return sizeof (struct sockaddr_in6);
@@ -2502,7 +2503,7 @@ get_lisp_to_sockaddr_size (address, fami
       struct sockaddr *sa;
       *familyp = XINT (XCAR (address));
       p = XVECTOR (XCDR (address));
-      return p->size + sizeof (sa->sa_family);
+      return p->header.size + sizeof (sa->sa_family);
     }
   return 0;
 }

=== modified file 'src/process.h'
--- src/process.h	2011-01-02 23:50:46 +0000
+++ src/process.h	2011-05-09 09:48:57 +0000
@@ -27,13 +27,13 @@ along with GNU Emacs.  If not, see <http
 /* This structure records information about a subprocess
    or network connection.
 
-   Every field in this structure except for the first two
+   Every field in this structure except for the header
    must be a Lisp_Object, for GC's sake.  */
 
 struct Lisp_Process
   {
-    EMACS_UINT size;
-    struct Lisp_Vector *v_next;
+    struct vectorlike_header header;
+
     /* Name of subprocess terminal.  */
     Lisp_Object tty_name;
     /* Name of this process */

=== modified file 'src/syntax.c'
--- src/syntax.c	2011-01-02 23:50:46 +0000
+++ src/syntax.c	2011-05-09 08:56:23 +0000
@@ -956,7 +956,7 @@ text property.  */)
 	break;
       }
 
-  if (val < XVECTOR (Vsyntax_code_object)->size && NILP (match))
+  if (val < XVECTOR_SIZE (Vsyntax_code_object) && NILP (match))
     return XVECTOR (Vsyntax_code_object)->contents[val];
   else
     /* Since we can't use a shared object, let's make a new one.  */
@@ -3348,7 +3348,7 @@ init_syntax_once ()
 
   /* Create objects which can be shared among syntax tables.  */
   Vsyntax_code_object = Fmake_vector (make_number (Smax), Qnil);
-  for (i = 0; i < XVECTOR (Vsyntax_code_object)->size; i++)
+  for (i = 0; i < XVECTOR_SIZE (Vsyntax_code_object); i++)
     XVECTOR (Vsyntax_code_object)->contents[i]
       = Fcons (make_number (i), Qnil);

=== modified file 'src/termhooks.h'
--- src/termhooks.h	2011-01-02 23:50:46 +0000
+++ src/termhooks.h	2011-05-09 09:48:57 +0000
@@ -325,10 +325,8 @@ struct w32_display_info;
 /* Terminal-local parameters. */
 struct terminal
 {
-  /* The first two fields are really the header of a vector */
-  /* The terminal code does not refer to them.  */
-  EMACS_UINT size;
-  struct Lisp_Vector *vec_next;
+  /* This is for Lisp; the terminal code does not refer to it.  */
+  struct vectorlike_header header;
 
   /* Parameter alist of this terminal.  */
   Lisp_Object param_alist;

=== modified file 'src/w32font.c'
--- src/w32font.c	2011-01-02 23:50:46 +0000
+++ src/w32font.c	2011-05-09 08:56:24 +0000
@@ -173,7 +173,7 @@ intern_font_name (string)
 
   /* The following code is copied from the function intern (in lread.c).  */
   obarray = Vobarray;
-  if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
+  if (!VECTORP (obarray) || XVECTOR_SIZE (obarray) == 0)
     obarray = check_obarray (obarray);
   tem = oblookup (obarray, SDATA (str), len, len);
   if (SYMBOLP (tem))

=== modified file 'src/w32menu.c'
--- src/w32menu.c	2011-01-02 23:50:46 +0000
+++ src/w32menu.c	2011-05-09 08:56:24 +0000
@@ -464,11 +464,11 @@ set_frame_menubar (f, first_time, deep_p
 
       menu_items = f->menu_bar_vector;
       menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
-      submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
-      submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
-      submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int));
+      submenu_start = (int *) alloca (XVECTOR_SIZE (items) * sizeof (int *));
+      submenu_end = (int *) alloca (XVECTOR_SIZE (items) * sizeof (int *));
+      submenu_n_panes = (int *) alloca (XVECTOR_SIZE (items) * sizeof (int));
       submenu_top_level_items
-	= (int *) alloca (XVECTOR (items)->size * sizeof (int *));
+	= (int *) alloca (XVECTOR_SIZE (items) * sizeof (int *));
       init_menu_items ();
       for (i = 0; i < ASIZE (items); i += 4)
 	{

=== modified file 'src/window.c'
--- src/window.c	2011-02-09 00:11:15 +0000
+++ src/window.c	2011-05-09 09:48:57 +0000
@@ -5931,8 +5931,7 @@ zero means top of window, negative means
 
 struct save_window_data
   {
-    EMACS_UINT size;
-    struct Lisp_Vector *next_from_Lisp_Vector_struct;
+    struct vectorlike_header header;
     Lisp_Object selected_frame;
     Lisp_Object current_window;
     Lisp_Object current_buffer;
@@ -5954,10 +5953,7 @@ struct save_window_data
 /* This is saved as a Lisp_Vector  */
 struct saved_window
 {
-  /* these first two must agree with struct Lisp_Vector in lisp.h */
-  EMACS_UINT size;
-  struct Lisp_Vector *next_from_Lisp_Vector_struct;
-
+  struct vectorlike_header header;
   Lisp_Object window;
   Lisp_Object buffer, start, pointm, mark;
   Lisp_Object left_col, top_line, total_cols, total_lines;
@@ -6141,7 +6137,7 @@ the return value is nil.  Otherwise the 
 	 dead.  */
       delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
 
-      for (k = 0; k < saved_windows->size; k++)
+      for (k = 0; k < saved_windows->header.size; k++)
 	{
 	  p = SAVED_WINDOW_N (saved_windows, k);
 	  w = XWINDOW (p->window);
@@ -7078,10 +7074,10 @@ compare_window_configurations (c1, c2, i
     return 0;
 
   /* Verify that the two confis have the same number of windows.  */
-  if (sw1->size != sw2->size)
+  if (sw1->header.size != sw2->header.size)
     return 0;
 
-  for (i = 0; i < sw1->size; i++)
+  for (i = 0; i < sw1->header.size; i++)
     {
       struct saved_window *p1, *p2;
       int w1_is_current, w2_is_current;

=== modified file 'src/window.h'
--- src/window.h	2011-01-02 23:50:46 +0000
+++ src/window.h	2011-05-09 09:48:57 +0000
@@ -89,10 +89,9 @@ struct cursor_pos
 
 struct window
   {
-    /* The first two fields are really the header of a vector */
-    /* The window code does not refer to them.  */
-    EMACS_UINT size;
-    struct Lisp_Vector *vec_next;
+    /* This is for Lisp; the terminal code does not refer to it.  */
+    struct vectorlike_header header;
+
     /* The frame this window is on.  */
     Lisp_Object frame;
     /* t if this window is a minibuffer window.  */

=== modified file 'src/xdisp.c'
--- src/xdisp.c	2011-04-13 18:19:23 +0000
+++ src/xdisp.c	2011-05-09 08:56:24 +0000
@@ -3865,7 +3865,7 @@ setup_for_ellipsis (it, len)
     {
       struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
       it->dpvec = v->contents;
-      it->dpend = v->contents + v->size;
+      it->dpend = v->contents + v->header.size;
     }
   else
     {
@@ -5697,11 +5697,11 @@ get_next_display_element (it)
 	      /* Return the first character from the display table
 		 entry, if not empty.  If empty, don't display the
 		 current character.  */
-	      if (v->size)
+	      if (v->header.size)
 		{
 		  it->dpvec_char_len = it->len;
 		  it->dpvec = v->contents;
-		  it->dpend = v->contents + v->size;
+		  it->dpend = v->contents + v->header.size;
 		  it->current.dpvec_index = 0;
 		  it->dpvec_face_id = -1;
 		  it->saved_face_id = it->face_id;
@@ -17087,7 +17087,7 @@ display_menu_bar (w)
 
   /* Display all items of the menu bar.  */
   items = FRAME_MENU_BAR_ITEMS (it.f);
-  for (i = 0; i < XVECTOR (items)->size; i += 4)
+  for (i = 0; i < XVECTOR_SIZE (items); i += 4)
     {
       Lisp_Object string;
 
@@ -23086,7 +23086,7 @@ on_hot_spot_p (hot_spot, x, y)
 	{
 	  struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
 	  Lisp_Object *poly = v->contents;
-	  int n = v->size;
+	  int n = v->header.size;
 	  int i;
 	  int inside = 0;
 	  Lisp_Object lx, ly;

=== modified file 'src/xfaces.c'
--- src/xfaces.c	2011-03-17 15:44:02 +0000
+++ src/xfaces.c	2011-05-09 08:56:24 +0000
@@ -1966,7 +1966,7 @@ the WIDTH times as wide as FACE on FRAME
 
 #define LFACEP(LFACE)					\
      (VECTORP (LFACE)					\
-      && XVECTOR (LFACE)->size == LFACE_VECTOR_SIZE	\
+      && XVECTOR_SIZE (LFACE) == LFACE_VECTOR_SIZE	\
       && EQ (AREF (LFACE, 0), Qface))

=== modified file 'src/xmenu.c'
--- src/xmenu.c	2011-04-08 20:41:28 +0000
+++ src/xmenu.c	2011-05-09 08:56:24 +0000
@@ -1012,6 +1012,7 @@ set_frame_menubar (f, first_time, deep_p
       Lisp_Object *previous_items
 	= (Lisp_Object *) alloca (previous_menu_items_used
 				  * sizeof (Lisp_Object));
+      EMACS_UINT subitems;
 
       /* If we are making a new widget, its contents are empty,
 	 do always reinitialize them.  */
@@ -1056,13 +1057,14 @@ set_frame_menubar (f, first_time, deep_p
 
       menu_items = f->menu_bar_vector;
       menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
-      submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
-      submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
-      submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int));
+      subitems = XVECTOR_SIZE (items) / 4;
+      submenu_start = (int *) alloca (subitems * sizeof (int *));
+      submenu_end = (int *) alloca (subitems * sizeof (int *));
+      submenu_n_panes = (int *) alloca (subitems * sizeof (int));
       submenu_top_level_items
-	= (int *) alloca (XVECTOR (items)->size * sizeof (int *));
+	= (int *) alloca (subitems * sizeof (int *));
       init_menu_items ();
-      for (i = 0; i < XVECTOR (items)->size; i += 4)
+      for (i = 0; i < subitems; i += 4)
 	{
 	  Lisp_Object key, string, maps;
 
@@ -1142,7 +1144,7 @@ set_frame_menubar (f, first_time, deep_p
       /* Now GC cannot happen during the lifetime of the widget_value,
 	 so it's safe to store data from a Lisp_String.  */
       wv = first_wv->contents;
-      for (i = 0; i < XVECTOR (items)->size; i += 4)
+      for (i = 0; i < XVECTOR_SIZE (items); i += 4)
 	{
 	  Lisp_Object string;
 	  string = XVECTOR (items)->contents[i + 1];
@@ -1168,7 +1170,7 @@ set_frame_menubar (f, first_time, deep_p
       first_wv = wv;
 
       items = FRAME_MENU_BAR_ITEMS (f);
-      for (i = 0; i < XVECTOR (items)->size; i += 4)
+      for (i = 0; i < XVECTOR_SIZE (items); i += 4)
 	{
 	  Lisp_Object string;

=== modified file 'src/xselect.c'
--- src/xselect.c	2011-04-08 20:41:28 +0000
+++ src/xselect.c	2011-05-09 08:56:24 +0000
@@ -486,7 +486,7 @@ x_get_local_selection (selection_symbol,
       int size;
       int i;
       pairs = XCDR (target_type);
-      size = XVECTOR (pairs)->size;
+      size = XVECTOR_SIZE (pairs);
       /* If the target is MULTIPLE, then target_type looks like
 	  (MULTIPLE . [[SELECTION1 TARGET1] [SELECTION2 TARGET2] ... ])
 	 We modify the second element of each pair in the vector and
@@ -1351,12 +1351,12 @@ copy_multiple_data (obj)
     return Fcons (XCAR (obj), copy_multiple_data (XCDR (obj)));
 
   CHECK_VECTOR (obj);
-  vec = Fmake_vector (size = XVECTOR (obj)->size, Qnil);
+  vec = Fmake_vector (size = XVECTOR_SIZE (obj), Qnil);
   for (i = 0; i < size; i++)
     {
       Lisp_Object vec2 = XVECTOR (obj)->contents [i];
       CHECK_VECTOR (vec2);
-      if (XVECTOR (vec2)->size != 2)
+      if (XVECTOR_SIZE (vec2) != 2)
 	/* ??? Confusing error message */
 	signal_error ("Vectors must be of length 2", vec2);
       XVECTOR (vec)->contents [i] = Fmake_vector (2, Qnil);
@@ -1996,7 +1996,7 @@ lisp_data_to_selection_data (display, ob
 	/* This vector is an ATOM set */
 	{
 	  if (NILP (type)) type = QATOM;
-	  *size_ret = XVECTOR (obj)->size;
+	  *size_ret = XVECTOR_SIZE (obj);
 	  *format_ret = 32;
 	  *data_ret = (unsigned char *) xmalloc ((*size_ret) * sizeof (Atom));
 	  for (i = 0; i < *size_ret; i++)
@@ -2011,7 +2011,7 @@ lisp_data_to_selection_data (display, ob
 	/* This vector is an ATOM_PAIR set */
 	{
 	  if (NILP (type)) type = QATOM_PAIR;
-	  *size_ret = XVECTOR (obj)->size;
+	  *size_ret = XVECTOR_SIZE (obj);
 	  *format_ret = 32;
 	  *data_ret = (unsigned char *)
 	    xmalloc ((*size_ret) * sizeof (Atom) * 2);
@@ -2019,7 +2019,7 @@ lisp_data_to_selection_data (display, ob
 	    if (VECTORP (XVECTOR (obj)->contents [i]))
 	      {
 		Lisp_Object pair = XVECTOR (obj)->contents [i];
-		if (XVECTOR (pair)->size != 2)
+		if (XVECTOR_SIZE (pair) != 2)
 		  signal_error (
 	"Elements of the vector must be vectors of exactly two elements",
 				pair);
@@ -2041,7 +2041,7 @@ lisp_data_to_selection_data (display, ob
 	/* This vector is an INTEGER set, or something like it */
 	{
           int data_size = 2;
-	  *size_ret = XVECTOR (obj)->size;
+	  *size_ret = XVECTOR_SIZE (obj);
 	  if (NILP (type)) type = QINTEGER;
 	  *format_ret = 16;
 	  for (i = 0; i < *size_ret; i++)
@@ -2095,7 +2095,7 @@ clean_local_selection_data (obj)
   if (VECTORP (obj))
     {
       int i;
-      int size = XVECTOR (obj)->size;
+      int size = XVECTOR_SIZE (obj);
       Lisp_Object copy;
       if (size == 1)
 	return clean_local_selection_data (XVECTOR (obj)->contents [0]);