Omit some unnecessary casts.
[bpt/emacs.git] / src / alloc.c
index 9536a1d..2c22326 100644 (file)
@@ -26,7 +26,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <limits.h>            /* For CHAR_BIT.  */
 
 #ifdef ENABLE_CHECKING
-#include <signal.h>            /* For SIGABRT. */
+#include <signal.h>            /* For SIGABRT.  */
 #endif
 
 #ifdef HAVE_PTHREAD
@@ -63,10 +63,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #endif
 
 #include <unistd.h>
-#ifndef HAVE_UNISTD_H
-extern void *sbrk ();
-#endif
-
 #include <fcntl.h>
 
 #ifdef USE_GTK
@@ -216,23 +212,18 @@ static Lisp_Object Qpost_gc_hook;
 static void mark_terminals (void);
 static void gc_sweep (void);
 static Lisp_Object make_pure_vector (ptrdiff_t);
-static void mark_glyph_matrix (struct glyph_matrix *);
-static void mark_face_cache (struct face_cache *);
 static void mark_buffer (struct buffer *);
 
 #if !defined REL_ALLOC || defined SYSTEM_MALLOC
 static void refill_memory_reserve (void);
 #endif
-static struct Lisp_String *allocate_string (void);
 static void compact_small_strings (void);
 static void free_large_strings (void);
-static void sweep_strings (void);
-static void free_misc (Lisp_Object);
 extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE;
 
-/* When scanning the C stack for live Lisp objects, Emacs keeps track
-   of what memory allocated via lisp_malloc is intended for what
-   purpose.  This enumeration specifies the type of memory.  */
+/* When scanning the C stack for live Lisp objects, Emacs keeps track of
+   what memory allocated via lisp_malloc and lisp_align_malloc is intended
+   for what purpose.  This enumeration specifies the type of memory.  */
 
 enum mem_type
 {
@@ -243,10 +234,9 @@ enum mem_type
   MEM_TYPE_MISC,
   MEM_TYPE_SYMBOL,
   MEM_TYPE_FLOAT,
-  /* We used to keep separate mem_types for subtypes of vectors such as
-     process, hash_table, frame, terminal, and window, but we never made
-     use of the distinction, so it only caused source-code complexity
-     and runtime slowdown.  Minor but pointless.  */
+  /* Since all non-bool pseudovectors are small enough to be
+     allocated from vector blocks, this memory type denotes
+     large regular vectors and large bool pseudovectors.  */
   MEM_TYPE_VECTORLIKE,
   /* Special type to denote vector blocks.  */
   MEM_TYPE_VECTOR_BLOCK,
@@ -254,15 +244,8 @@ enum mem_type
   MEM_TYPE_SPARE
 };
 
-static void *lisp_malloc (size_t, enum mem_type);
-
-
 #if GC_MARK_STACK || defined GC_MALLOC_CHECK
 
-#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
-#include <stdio.h>             /* For fprintf.  */
-#endif
-
 /* A unique object in pure space used to make some Lisp objects
    on free lists recognizable in O(1).  */
 
@@ -335,20 +318,7 @@ static void *min_heap_address, *max_heap_address;
 static struct mem_node mem_z;
 #define MEM_NIL &mem_z
 
-static struct Lisp_Vector *allocate_vectorlike (ptrdiff_t);
-static void lisp_free (void *);
-static void mark_stack (void);
-static bool live_vector_p (struct mem_node *, void *);
-static bool live_buffer_p (struct mem_node *, void *);
-static bool live_string_p (struct mem_node *, void *);
-static bool live_cons_p (struct mem_node *, void *);
-static bool live_symbol_p (struct mem_node *, void *);
-static bool live_float_p (struct mem_node *, void *);
-static bool live_misc_p (struct mem_node *, void *);
-static void mark_maybe_object (Lisp_Object);
-static void mark_memory (void *, void *);
 #if GC_MARK_STACK || defined GC_MALLOC_CHECK
-static void mem_init (void);
 static struct mem_node *mem_insert (void *, void *, enum mem_type);
 static void mem_insert_fixup (struct mem_node *);
 static void mem_rotate_left (struct mem_node *);
@@ -358,11 +328,6 @@ static void mem_delete_fixup (struct mem_node *);
 static struct mem_node *mem_find (void *);
 #endif
 
-
-#if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS
-static void check_gcpros (void);
-#endif
-
 #endif /* GC_MARK_STACK || GC_MALLOC_CHECK */
 
 #ifndef DEADP
@@ -376,7 +341,7 @@ struct gcpro *gcprolist;
 /* Addresses of staticpro'd variables.  Initialize it to a nonzero
    value; otherwise some compilers put it into BSS.  */
 
-#define NSTATICS 0x800
+enum { NSTATICS = 2048 };
 static Lisp_Object *staticvec[NSTATICS] = {&Vpurify_flag};
 
 /* Index of next unused slot in staticvec.  */
@@ -393,6 +358,11 @@ static void *pure_alloc (size_t, int);
   ((void *) (((uintptr_t) (ptr) + (ALIGNMENT) - 1) \
             & ~ ((ALIGNMENT) - 1)))
 
+static void
+XFLOAT_INIT (Lisp_Object f, double n)
+{
+  XFLOAT (f)->u.data = n;
+}
 
 \f
 /************************************************************************
@@ -434,11 +404,11 @@ buffer_memory_full (ptrdiff_t nbytes)
 
 #ifndef REL_ALLOC
   memory_full (nbytes);
-#endif
-
+#else
   /* This used to call error, but if we've run out of memory, we could
      get infinite recursion trying to build the string.  */
   xsignal (Qnil, Vmemory_signal_data);
+#endif
 }
 
 /* A common multiple of the positive integers A and B.  Ideally this
@@ -773,13 +743,17 @@ xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size)
    infinity.
 
    If PA is null, then allocate a new array instead of reallocating
-   the old one.  Thus, to grow an array A without saving its old
-   contents, invoke xfree (A) immediately followed by xgrowalloc (0,
-   &NITEMS, ...).
+   the old one.
 
    Block interrupt input as needed.  If memory exhaustion occurs, set
    *NITEMS to zero if PA is null, and signal an error (i.e., do not
-   return).  */
+   return).
+
+   Thus, to grow an array A without saving its old contents, do
+   { xfree (A); A = NULL; A = xpalloc (NULL, &AITEMS, ...); }.
+   The A = NULL avoids a dangling pointer if xpalloc exhausts memory
+   and signals an error, and later this code is reexecuted and
+   attempts to free A.  */
 
 void *
 xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
@@ -822,25 +796,20 @@ xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
 char *
 xstrdup (const char *s)
 {
-  size_t len = strlen (s) + 1;
-  char *p = xmalloc (len);
-  memcpy (p, s, len);
-  return p;
+  ptrdiff_t size;
+  eassert (s);
+  size = strlen (s) + 1;
+  return memcpy (xmalloc (size), s, size);
 }
 
+/* Like putenv, but (1) use the equivalent of xmalloc and (2) the
+   argument is a const pointer.  */
 
-/* Unwind for SAFE_ALLOCA */
-
-Lisp_Object
-safe_alloca_unwind (Lisp_Object arg)
+void
+xputenv (char const *string)
 {
-  register struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
-
-  p->dogc = 0;
-  xfree (p->pointer);
-  p->pointer = 0;
-  free_misc (arg);
-  return Qnil;
+  if (putenv ((char *) string) != 0)
+    memory_full (0);
 }
 
 /* Return a newly allocated memory block of SIZE bytes, remembering
@@ -849,7 +818,7 @@ void *
 record_xmalloc (size_t size)
 {
   void *p = xmalloc (size);
-  record_unwind_protect (safe_alloca_unwind, make_save_value (p, 0));
+  record_unwind_protect_ptr (xfree, p);
   return p;
 }
 
@@ -1166,7 +1135,7 @@ lisp_align_free (void *block)
 #define INTERVAL_BLOCK_SIZE \
   ((1020 - sizeof (struct interval_block *)) / sizeof (struct interval))
 
-/* Intervals are allocated in chunks in form of an interval_block
+/* Intervals are allocated in chunks in the form of an interval_block
    structure.  */
 
 struct interval_block
@@ -1277,7 +1246,7 @@ mark_interval (register INTERVAL i, Lisp_Object dummy)
    When a Lisp_String is freed during GC, it is put back on
    string_free_list, and its `data' member and its sdata's `string'
    pointer is set to null.  The size of the string is recorded in the
-   `u.nbytes' member of the sdata.  So, sdata structures that are no
+   `n.nbytes' member of the sdata.  So, sdata structures that are no
    longer used, can be easily recognized, and it's easy to compact the
    sblocks of small strings which we do in compact_small_strings.  */
 
@@ -1291,10 +1260,12 @@ mark_interval (register INTERVAL i, Lisp_Object dummy)
 
 #define LARGE_STRING_BYTES 1024
 
-/* Structure describing string memory sub-allocated from an sblock.
+/* Struct or union describing string memory sub-allocated from an sblock.
    This is where the contents of Lisp strings are stored.  */
 
-struct sdata
+#ifdef GC_CHECK_STRING_BYTES
+
+typedef struct
 {
   /* Back-pointer to the string this sdata belongs to.  If null, this
      structure is free, and the NBYTES member of the union below
@@ -1304,34 +1275,42 @@ struct sdata
      contents.  */
   struct Lisp_String *string;
 
-#ifdef GC_CHECK_STRING_BYTES
-
   ptrdiff_t nbytes;
-  unsigned char data[1];
+  unsigned char data[FLEXIBLE_ARRAY_MEMBER];
+} sdata;
 
 #define SDATA_NBYTES(S)        (S)->nbytes
 #define SDATA_DATA(S)  (S)->data
 #define SDATA_SELECTOR(member) member
 
-#else /* not GC_CHECK_STRING_BYTES */
+#else
 
-  union
+typedef union
+{
+  struct Lisp_String *string;
+
+  /* When STRING is non-null.  */
+  struct
   {
-    /* When STRING is non-null.  */
-    unsigned char data[1];
+    struct Lisp_String *string;
+    unsigned char data[FLEXIBLE_ARRAY_MEMBER];
+  } u;
 
-    /* When STRING is null.  */
+  /* When STRING is null.  */
+  struct
+  {
+    struct Lisp_String *string;
     ptrdiff_t nbytes;
-  } u;
+  } n;
+} sdata;
 
-#define SDATA_NBYTES(S)        (S)->u.nbytes
+#define SDATA_NBYTES(S)        (S)->n.nbytes
 #define SDATA_DATA(S)  (S)->u.data
 #define SDATA_SELECTOR(member) u.member
 
 #endif /* not GC_CHECK_STRING_BYTES */
 
-#define SDATA_DATA_OFFSET offsetof (struct sdata, SDATA_SELECTOR (data))
-};
+#define SDATA_DATA_OFFSET offsetof (sdata, SDATA_SELECTOR (data))
 
 
 /* Structure describing a block of memory which is sub-allocated to
@@ -1346,10 +1325,10 @@ struct sblock
 
   /* Pointer to the next free sdata block.  This points past the end
      of the sblock if there isn't any space left in this block.  */
-  struct sdata *next_free;
+  sdata *next_free;
 
   /* Start of data.  */
-  struct sdata first_data;
+  sdata first_data;
 };
 
 /* Number of Lisp strings in a string_block structure.  The 1020 is
@@ -1405,7 +1384,7 @@ static EMACS_INT total_string_bytes;
    a pointer to the `u.data' member of its sdata structure; the
    structure starts at a constant offset in front of that.  */
 
-#define SDATA_OF_STRING(S) ((struct sdata *) ((S)->data - SDATA_DATA_OFFSET))
+#define SDATA_OF_STRING(S) ((sdata *) ((S)->data - SDATA_DATA_OFFSET))
 
 
 #ifdef GC_CHECK_STRING_OVERRUN
@@ -1504,7 +1483,7 @@ string_bytes (struct Lisp_String *s)
 static void
 check_sblock (struct sblock *b)
 {
-  struct sdata *from, *end, *from_end;
+  sdata *from, *end, *from_end;
 
   end = b->next_free;
 
@@ -1518,7 +1497,7 @@ check_sblock (struct sblock *b)
         same as the one recorded in the sdata structure.  */
       nbytes = SDATA_SIZE (from->string ? string_bytes (from->string)
                           : SDATA_NBYTES (from));
-      from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA);
+      from_end = (sdata *) ((char *) from + nbytes + GC_STRING_EXTRA);
     }
 }
 
@@ -1648,7 +1627,7 @@ void
 allocate_string_data (struct Lisp_String *s,
                      EMACS_INT nchars, EMACS_INT nbytes)
 {
-  struct sdata *data, *old_data;
+  sdata *data, *old_data;
   struct sblock *b;
   ptrdiff_t needed, old_nbytes;
 
@@ -1688,7 +1667,7 @@ allocate_string_data (struct Lisp_String *s,
       b = lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP);
 
 #ifdef DOUG_LEA_MALLOC
-      /* Back to a reasonable maximum of mmap'ed areas. */
+      /* Back to a reasonable maximum of mmap'ed areas.  */
       mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
 #endif
 
@@ -1718,7 +1697,7 @@ allocate_string_data (struct Lisp_String *s,
     b = current_sblock;
 
   data = b->next_free;
-  b->next_free = (struct sdata *) ((char *) data + needed + GC_STRING_EXTRA);
+  b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA);
 
   MALLOC_UNBLOCK_INPUT;
 
@@ -1789,7 +1768,7 @@ sweep_strings (void)
              else
                {
                  /* String is dead.  Put it on the free-list.  */
-                 struct sdata *data = SDATA_OF_STRING (s);
+                 sdata *data = SDATA_OF_STRING (s);
 
                  /* Save the size of S in its sdata so that we know
                     how large that is.  Reset the sdata's string
@@ -1798,7 +1777,7 @@ sweep_strings (void)
                  if (string_bytes (s) != SDATA_NBYTES (data))
                    emacs_abort ();
 #else
-                 data->u.nbytes = STRING_BYTES (s);
+                 data->n.nbytes = STRING_BYTES (s);
 #endif
                  data->string = NULL;
 
@@ -1879,13 +1858,13 @@ static void
 compact_small_strings (void)
 {
   struct sblock *b, *tb, *next;
-  struct sdata *from, *to, *end, *tb_end;
-  struct sdata *to_end, *from_end;
+  sdata *from, *to, *end, *tb_end;
+  sdata *to_end, *from_end;
 
   /* TB is the sblock we copy to, TO is the sdata within TB we copy
      to, and TB_END is the end of TB.  */
   tb = oldest_sblock;
-  tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE);
+  tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE);
   to = &tb->first_data;
 
   /* Step through the blocks from the oldest to the youngest.  We
@@ -1905,7 +1884,7 @@ compact_small_strings (void)
 
 #ifdef GC_CHECK_STRING_BYTES
          /* Check that the string size recorded in the string is the
-            same as the one recorded in the sdata structure. */
+            same as the one recorded in the sdata structure.  */
          if (s && string_bytes (s) != SDATA_NBYTES (from))
            emacs_abort ();
 #endif /* GC_CHECK_STRING_BYTES */
@@ -1914,7 +1893,7 @@ compact_small_strings (void)
          eassert (nbytes <= LARGE_STRING_BYTES);
 
          nbytes = SDATA_SIZE (nbytes);
-         from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA);
+         from_end = (sdata *) ((char *) from + nbytes + GC_STRING_EXTRA);
 
 #ifdef GC_CHECK_STRING_OVERRUN
          if (memcmp (string_overrun_cookie,
@@ -1927,14 +1906,14 @@ compact_small_strings (void)
          if (s)
            {
              /* If TB is full, proceed with the next sblock.  */
-             to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA);
+             to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA);
              if (to_end > tb_end)
                {
                  tb->next_free = to;
                  tb = tb->next;
-                 tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE);
+                 tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE);
                  to = &tb->first_data;
-                 to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA);
+                 to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA);
                }
 
              /* Copy, and update the string's `data' pointer.  */
@@ -2040,7 +2019,7 @@ LENGTH must be a number.  INIT matters only in whether it is t or nil.  */)
   val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil);
 
   /* No Lisp_Object to trace in there.  */
-  XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0);
+  XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0);
 
   p = XBOOL_VECTOR (val);
   p->size = XFASTINT (length);
@@ -2598,7 +2577,7 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
 
 /* Size of the minimal vector allocated from block.  */
 
-#define VBLOCK_BYTES_MIN vroundup (sizeof (struct Lisp_Vector))
+#define VBLOCK_BYTES_MIN vroundup (header_size + sizeof (Lisp_Object))
 
 /* Size of the largest vector allocated from block.  */
 
@@ -2619,19 +2598,54 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
 
 #define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size)
 
+/* Get and set the next field in block-allocated vectorlike objects on
+   the free list.  Doing it this way respects C's aliasing rules.
+   We could instead make 'contents' a union, but that would mean
+   changes everywhere that the code uses 'contents'.  */
+static struct Lisp_Vector *
+next_in_free_list (struct Lisp_Vector *v)
+{
+  intptr_t i = XLI (v->contents[0]);
+  return (struct Lisp_Vector *) i;
+}
+static void
+set_next_in_free_list (struct Lisp_Vector *v, struct Lisp_Vector *next)
+{
+  v->contents[0] = XIL ((intptr_t) next);
+}
+
 /* Common shortcut to setup vector on a free list.  */
 
-#define SETUP_ON_FREE_LIST(v, nbytes, index)                   \
-  do {                                                         \
-    XSETPVECTYPESIZE (v, PVEC_FREE, nbytes);                   \
-    eassert ((nbytes) % roundup_size == 0);                    \
-    (index) = VINDEX (nbytes);                                 \
-    eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX);            \
-    (v)->header.next.vector = vector_free_lists[index];                \
-    vector_free_lists[index] = (v);                            \
-    total_free_vector_slots += (nbytes) / word_size;           \
+#define SETUP_ON_FREE_LIST(v, nbytes, tmp)             \
+  do {                                                 \
+    (tmp) = ((nbytes - header_size) / word_size);      \
+    XSETPVECTYPESIZE (v, PVEC_FREE, 0, (tmp));         \
+    eassert ((nbytes) % roundup_size == 0);            \
+    (tmp) = VINDEX (nbytes);                           \
+    eassert ((tmp) < VECTOR_MAX_FREE_LIST_INDEX);      \
+    set_next_in_free_list (v, vector_free_lists[tmp]); \
+    vector_free_lists[tmp] = (v);                      \
+    total_free_vector_slots += (nbytes) / word_size;   \
   } while (0)
 
+/* This internal type is used to maintain the list of large vectors
+   which are allocated at their own, e.g. outside of vector blocks.  */
+
+struct large_vector
+{
+  union {
+    struct large_vector *vector;
+#if USE_LSB_TAG
+    /* We need to maintain ROUNDUP_SIZE alignment for the vector member.  */
+    unsigned char c[vroundup (sizeof (struct large_vector *))];
+#endif
+  } next;
+  struct Lisp_Vector v;
+};
+
+/* This internal type is used to maintain an underlying storage
+   for small vectors.  */
+
 struct vector_block
 {
   char data[VECTOR_BLOCK_BYTES];
@@ -2649,7 +2663,7 @@ static struct Lisp_Vector *vector_free_lists[VECTOR_MAX_FREE_LIST_INDEX];
 
 /* Singly-linked list of large vectors.  */
 
-static struct Lisp_Vector *large_vectors;
+static struct large_vector *large_vectors;
 
 /* The only vector with 0 slots, allocated from pure space.  */
 
@@ -2693,7 +2707,7 @@ init_vectors (void)
 static struct Lisp_Vector *
 allocate_vector_from_block (size_t nbytes)
 {
-  struct Lisp_Vector *vector, *rest;
+  struct Lisp_Vector *vector;
   struct vector_block *block;
   size_t index, restbytes;
 
@@ -2706,8 +2720,7 @@ allocate_vector_from_block (size_t nbytes)
   if (vector_free_lists[index])
     {
       vector = vector_free_lists[index];
-      vector_free_lists[index] = vector->header.next.vector;
-      vector->header.next.nbytes = nbytes;
+      vector_free_lists[index] = next_in_free_list (vector);
       total_free_vector_slots -= nbytes / word_size;
       return vector;
     }
@@ -2721,16 +2734,14 @@ allocate_vector_from_block (size_t nbytes)
       {
        /* This vector is larger than requested.  */
        vector = vector_free_lists[index];
-       vector_free_lists[index] = vector->header.next.vector;
-       vector->header.next.nbytes = nbytes;
+       vector_free_lists[index] = next_in_free_list (vector);
        total_free_vector_slots -= nbytes / word_size;
 
        /* Excess bytes are used for the smaller vector,
           which should be set on an appropriate free list.  */
        restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes;
        eassert (restbytes % roundup_size == 0);
-       rest = ADVANCE (vector, nbytes);
-       SETUP_ON_FREE_LIST (rest, restbytes, index);
+       SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index);
        return vector;
       }
 
@@ -2739,7 +2750,6 @@ allocate_vector_from_block (size_t nbytes)
 
   /* New vector will be at the beginning of this block.  */
   vector = (struct Lisp_Vector *) block->data;
-  vector->header.next.nbytes = nbytes;
 
   /* If the rest of space from this block is large enough
      for one-slot vector at least, set up it on a free list.  */
@@ -2747,11 +2757,10 @@ allocate_vector_from_block (size_t nbytes)
   if (restbytes >= VBLOCK_BYTES_MIN)
     {
       eassert (restbytes % roundup_size == 0);
-      rest = ADVANCE (vector, nbytes);
-      SETUP_ON_FREE_LIST (rest, restbytes, index);
+      SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index);
     }
   return vector;
- }
+}
 
 /* Nonzero if VECTOR pointer is valid pointer inside BLOCK.  */
 
@@ -2759,15 +2768,30 @@ allocate_vector_from_block (size_t nbytes)
   ((char *) (vector) <= (block)->data          \
    + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN)
 
-/* Number of bytes used by vector-block-allocated object.  This is the only
-   place where we actually use the `nbytes' field of the vector-header.
-   I.e. we could get rid of the `nbytes' field by computing it based on the
-   vector-type.  */
+/* Return the memory footprint of V in bytes.  */
+
+static ptrdiff_t
+vector_nbytes (struct Lisp_Vector *v)
+{
+  ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG;
 
-#define PSEUDOVECTOR_NBYTES(vector) \
-  (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE)     \
-   ? vector->header.size & PSEUDOVECTOR_SIZE_MASK      \
-   : vector->header.next.nbytes)
+  if (size & PSEUDOVECTOR_FLAG)
+    {
+      if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR))
+       size = (bool_header_size
+               + (((struct Lisp_Bool_Vector *) v)->size
+                  + BOOL_VECTOR_BITS_PER_CHAR - 1)
+               / BOOL_VECTOR_BITS_PER_CHAR);
+      else
+       size = (header_size
+               + ((size & PSEUDOVECTOR_SIZE_MASK)
+                  + ((size & PSEUDOVECTOR_REST_MASK)
+                     >> PSEUDOVECTOR_SIZE_BITS)) * word_size);
+    }
+  else
+    size = header_size + size * word_size;
+  return vroundup (size);
+}
 
 /* Reclaim space used by unmarked vectors.  */
 
@@ -2775,7 +2799,8 @@ static void
 sweep_vectors (void)
 {
   struct vector_block *block = vector_blocks, **bprev = &vector_blocks;
-  struct Lisp_Vector *vector, *next, **vprev = &large_vectors;
+  struct large_vector *lv, **lvprev = &large_vectors;
+  struct Lisp_Vector *vector, *next;
 
   total_vectors = total_vector_slots = total_free_vector_slots = 0;
   memset (vector_free_lists, 0, sizeof (vector_free_lists));
@@ -2785,6 +2810,7 @@ sweep_vectors (void)
   for (block = vector_blocks; block; block = *bprev)
     {
       bool free_this_block = 0;
+      ptrdiff_t nbytes;
 
       for (vector = (struct Lisp_Vector *) block->data;
           VECTOR_IN_BLOCK (vector, block); vector = next)
@@ -2793,14 +2819,16 @@ sweep_vectors (void)
            {
              VECTOR_UNMARK (vector);
              total_vectors++;
-             total_vector_slots += vector->header.next.nbytes / word_size;
-             next = ADVANCE (vector, vector->header.next.nbytes);
+             nbytes = vector_nbytes (vector);
+             total_vector_slots += nbytes / word_size;
+             next = ADVANCE (vector, nbytes);
            }
          else
            {
-             ptrdiff_t nbytes = PSEUDOVECTOR_NBYTES (vector);
-             ptrdiff_t total_bytes = nbytes;
+             ptrdiff_t total_bytes;
 
+             nbytes = vector_nbytes (vector);
+             total_bytes = nbytes;
              next = ADVANCE (vector, nbytes);
 
              /* While NEXT is not marked, try to coalesce with VECTOR,
@@ -2810,7 +2838,7 @@ sweep_vectors (void)
                {
                  if (VECTOR_MARKED_P (next))
                    break;
-                 nbytes = PSEUDOVECTOR_NBYTES (next);
+                 nbytes = vector_nbytes (next);
                  total_bytes += nbytes;
                  next = ADVANCE (next, nbytes);
                }
@@ -2844,8 +2872,9 @@ sweep_vectors (void)
 
   /* Sweep large vectors.  */
 
-  for (vector = large_vectors; vector; vector = *vprev)
+  for (lv = large_vectors; lv; lv = *lvprev)
     {
+      vector = &lv->v;
       if (VECTOR_MARKED_P (vector))
        {
          VECTOR_UNMARK (vector);
@@ -2867,12 +2896,12 @@ sweep_vectors (void)
          else
            total_vector_slots
              += header_size / word_size + vector->header.size;
-         vprev = &vector->header.next.vector;
+         lvprev = &lv->next.vector;
        }
       else
        {
-         *vprev = vector->header.next.vector;
-         lisp_free (vector);
+         *lvprev = lv->next.vector;
+         lisp_free (lv);
        }
     }
 }
@@ -2904,9 +2933,13 @@ allocate_vectorlike (ptrdiff_t len)
        p = allocate_vector_from_block (vroundup (nbytes));
       else
        {
-         p = lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE);
-         p->header.next.vector = large_vectors;
-         large_vectors = p;
+         struct large_vector *lv
+           = lisp_malloc ((offsetof (struct large_vector, v.contents)
+                           + len * word_size),
+                          MEM_TYPE_VECTORLIKE);
+         lv->next.vector = large_vectors;
+         large_vectors = lv;
+         p = &lv->v;
        }
 
 #ifdef DOUG_LEA_MALLOC
@@ -2943,16 +2976,21 @@ allocate_vector (EMACS_INT len)
 /* Allocate other vector-like structures.  */
 
 struct Lisp_Vector *
-allocate_pseudovector (int memlen, int lisplen, int tag)
+allocate_pseudovector (int memlen, int lisplen, enum pvec_type tag)
 {
   struct Lisp_Vector *v = allocate_vectorlike (memlen);
   int i;
 
+  /* Catch bogus values.  */
+  eassert (tag <= PVEC_FONT);
+  eassert (memlen - lisplen <= (1 << PSEUDOVECTOR_REST_BITS) - 1);
+  eassert (lisplen <= (1 << PSEUDOVECTOR_SIZE_BITS) - 1);
+
   /* Only the first lisplen slots will be traced normally by the GC.  */
   for (i = 0; i < lisplen; ++i)
     v->contents[i] = Qnil;
 
-  XSETPVECTYPESIZE (v, tag, lisplen);
+  XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen);
   return v;
 }
 
@@ -2961,10 +2999,9 @@ allocate_buffer (void)
 {
   struct buffer *b = lisp_malloc (sizeof *b, MEM_TYPE_BUFFER);
 
-  XSETPVECTYPESIZE (b, PVEC_BUFFER, (offsetof (struct buffer, own_text)
-                                    - header_size) / word_size);
+  BUFFER_PVEC_INIT (b);
   /* Put B on the chain of all buffers including killed ones.  */
-  b->header.next.buffer = all_buffers;
+  b->next = all_buffers;
   all_buffers = b;
   /* Note that the rest fields of B are not initialized.  */
   return b;
@@ -3052,13 +3089,10 @@ Any number of arguments, even zero arguments, are allowed.
 usage: (vector &rest OBJECTS)  */)
   (ptrdiff_t nargs, Lisp_Object *args)
 {
-  register Lisp_Object len, val;
   ptrdiff_t i;
-  register struct Lisp_Vector *p;
+  register Lisp_Object val = make_uninit_vector (nargs);
+  register struct Lisp_Vector *p = XVECTOR (val);
 
-  XSETFASTINT (len, nargs);
-  val = Fmake_vector (len, Qnil);
-  p = XVECTOR (val);
   for (i = 0; i < nargs; i++)
     p->contents[i] = args[i];
   return val;
@@ -3096,9 +3130,9 @@ stack before executing the byte-code.
 usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INTERACTIVE-SPEC &rest ELEMENTS)  */)
   (ptrdiff_t nargs, Lisp_Object *args)
 {
-  register Lisp_Object len, val;
   ptrdiff_t i;
-  register struct Lisp_Vector *p;
+  register Lisp_Object val = make_uninit_vector (nargs);
+  register struct Lisp_Vector *p = XVECTOR (val);
 
   /* We used to purecopy everything here, if purify-flag was set.  This worked
      OK for Emacs-23, but with Emacs-24's lexical binding code, it can be
@@ -3108,10 +3142,6 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT
      just wasteful and other times plainly wrong (e.g. those free vars may want
      to be setcar'd).  */
 
-  XSETFASTINT (len, nargs);
-  val = Fmake_vector (len, Qnil);
-
-  p = XVECTOR (val);
   for (i = 0; i < nargs; i++)
     p->contents[i] = args[i];
   make_byte_code (p);
@@ -3161,9 +3191,15 @@ static int symbol_block_index = SYMBOL_BLOCK_SIZE;
 
 static struct Lisp_Symbol *symbol_free_list;
 
+static void
+set_symbol_name (Lisp_Object sym, Lisp_Object name)
+{
+  XSYMBOL (sym)->name = name;
+}
+
 DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0,
        doc: /* Return a newly allocated uninterned symbol whose name is NAME.
-Its value and function definition are void, and its property list is nil.  */)
+Its value is void, and its function definition and property list are nil.  */)
   (Lisp_Object name)
 {
   register Lisp_Object val;
@@ -3200,7 +3236,7 @@ Its value and function definition are void, and its property list is nil.  */)
   set_symbol_plist (val, Qnil);
   p->redirect = SYMBOL_PLAINVAL;
   SET_SYMBOL_VAL (p, Qunbound);
-  set_symbol_function (val, Qunbound);
+  set_symbol_function (val, Qnil);
   set_symbol_next (val, NULL);
   p->gcmarkbit = 0;
   p->interned = SYMBOL_UNINTERNED;
@@ -3281,41 +3317,132 @@ allocate_misc (enum Lisp_Misc_Type type)
   --total_free_markers;
   consing_since_gc += sizeof (union Lisp_Misc);
   misc_objects_consed++;
-  XMISCTYPE (val) = type;
+  XMISCANY (val)->type = type;
   XMISCANY (val)->gcmarkbit = 0;
   return val;
 }
 
-/* Free a Lisp_Misc object */
+/* Free a Lisp_Misc object */
 
-static void
+void
 free_misc (Lisp_Object misc)
 {
-  XMISCTYPE (misc) = Lisp_Misc_Free;
+  XMISCANY (misc)->type = Lisp_Misc_Free;
   XMISC (misc)->u_free.chain = marker_free_list;
   marker_free_list = XMISC (misc);
   consing_since_gc -= sizeof (union Lisp_Misc);
   total_free_markers++;
 }
 
-/* Return a Lisp_Misc_Save_Value object containing POINTER and
-   INTEGER.  This is used to package C values to call record_unwind_protect.
-   The unwind function can get the C values back using XSAVE_VALUE.  */
+/* Verify properties of Lisp_Save_Value's representation
+   that are assumed here and elsewhere.  */
+
+verify (SAVE_UNUSED == 0);
+verify (((SAVE_INTEGER | SAVE_POINTER | SAVE_FUNCPOINTER | SAVE_OBJECT)
+        >> SAVE_SLOT_BITS)
+       == 0);
+
+/* Return Lisp_Save_Value objects for the various combinations
+   that callers need.  */
+
+Lisp_Object
+make_save_int_int_int (ptrdiff_t a, ptrdiff_t b, ptrdiff_t c)
+{
+  Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+  struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+  p->save_type = SAVE_TYPE_INT_INT_INT;
+  p->data[0].integer = a;
+  p->data[1].integer = b;
+  p->data[2].integer = c;
+  return val;
+}
+
+Lisp_Object
+make_save_obj_obj_obj_obj (Lisp_Object a, Lisp_Object b, Lisp_Object c,
+                          Lisp_Object d)
+{
+  Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+  struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+  p->save_type = SAVE_TYPE_OBJ_OBJ_OBJ_OBJ;
+  p->data[0].object = a;
+  p->data[1].object = b;
+  p->data[2].object = c;
+  p->data[3].object = d;
+  return val;
+}
 
+#if defined HAVE_NS || defined HAVE_NTGUI
 Lisp_Object
-make_save_value (void *pointer, ptrdiff_t integer)
+make_save_ptr (void *a)
 {
-  register Lisp_Object val;
-  register struct Lisp_Save_Value *p;
+  Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+  struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+  p->save_type = SAVE_POINTER;
+  p->data[0].pointer = a;
+  return val;
+}
+#endif
+
+Lisp_Object
+make_save_ptr_int (void *a, ptrdiff_t b)
+{
+  Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+  struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+  p->save_type = SAVE_TYPE_PTR_INT;
+  p->data[0].pointer = a;
+  p->data[1].integer = b;
+  return val;
+}
+
+#if defined HAVE_MENUS && ! (defined USE_X_TOOLKIT || defined USE_GTK)
+Lisp_Object
+make_save_ptr_ptr (void *a, void *b)
+{
+  Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+  struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+  p->save_type = SAVE_TYPE_PTR_PTR;
+  p->data[0].pointer = a;
+  p->data[1].pointer = b;
+  return val;
+}
+#endif
+
+Lisp_Object
+make_save_funcptr_ptr_obj (void (*a) (void), void *b, Lisp_Object c)
+{
+  Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+  struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+  p->save_type = SAVE_TYPE_FUNCPTR_PTR_OBJ;
+  p->data[0].funcpointer = a;
+  p->data[1].pointer = b;
+  p->data[2].object = c;
+  return val;
+}
 
-  val = allocate_misc (Lisp_Misc_Save_Value);
-  p = XSAVE_VALUE (val);
-  p->pointer = pointer;
-  p->integer = integer;
-  p->dogc = 0;
+/* Return a Lisp_Save_Value object that represents an array A
+   of N Lisp objects.  */
+
+Lisp_Object
+make_save_memory (Lisp_Object *a, ptrdiff_t n)
+{
+  Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+  struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+  p->save_type = SAVE_TYPE_MEMORY;
+  p->data[0].pointer = a;
+  p->data[1].integer = n;
   return val;
 }
 
+/* Free a Lisp_Save_Value object.  Do not use this function
+   if SAVE contains pointer other than returned by xmalloc.  */
+
+void
+free_save_value (Lisp_Object save)
+{
+  xfree (XSAVE_POINTER (save, 0));
+  free_misc (save);
+}
+
 /* Return a Lisp_Misc_Overlay object with specified START, END and PLIST.  */
 
 Lisp_Object
@@ -3931,7 +4058,7 @@ live_string_p (struct mem_node *m, void *p)
 {
   if (m->type == MEM_TYPE_STRING)
     {
-      struct string_block *b = (struct string_block *) m->start;
+      struct string_block *b = m->start;
       ptrdiff_t offset = (char *) p - (char *) &b->strings[0];
 
       /* P must point to the start of a Lisp_String structure, and it
@@ -3954,7 +4081,7 @@ live_cons_p (struct mem_node *m, void *p)
 {
   if (m->type == MEM_TYPE_CONS)
     {
-      struct cons_block *b = (struct cons_block *) m->start;
+      struct cons_block *b = m->start;
       ptrdiff_t offset = (char *) p - (char *) &b->conses[0];
 
       /* P must point to the start of a Lisp_Cons, not be
@@ -3980,7 +4107,7 @@ live_symbol_p (struct mem_node *m, void *p)
 {
   if (m->type == MEM_TYPE_SYMBOL)
     {
-      struct symbol_block *b = (struct symbol_block *) m->start;
+      struct symbol_block *b = m->start;
       ptrdiff_t offset = (char *) p - (char *) &b->symbols[0];
 
       /* P must point to the start of a Lisp_Symbol, not be
@@ -4006,7 +4133,7 @@ live_float_p (struct mem_node *m, void *p)
 {
   if (m->type == MEM_TYPE_FLOAT)
     {
-      struct float_block *b = (struct float_block *) m->start;
+      struct float_block *b = m->start;
       ptrdiff_t offset = (char *) p - (char *) &b->floats[0];
 
       /* P must point to the start of a Lisp_Float and not be
@@ -4030,7 +4157,7 @@ live_misc_p (struct mem_node *m, void *p)
 {
   if (m->type == MEM_TYPE_MISC)
     {
-      struct marker_block *b = (struct marker_block *) m->start;
+      struct marker_block *b = m->start;
       ptrdiff_t offset = (char *) p - (char *) &b->markers[0];
 
       /* P must point to the start of a Lisp_Misc, not be
@@ -4057,7 +4184,7 @@ live_vector_p (struct mem_node *m, void *p)
   if (m->type == MEM_TYPE_VECTOR_BLOCK)
     {
       /* This memory node corresponds to a vector block.  */
-      struct vector_block *block = (struct vector_block *) m->start;
+      struct vector_block *block = m->start;
       struct Lisp_Vector *vector = (struct Lisp_Vector *) block->data;
 
       /* P is in the block's allocation range.  Scan the block
@@ -4068,16 +4195,15 @@ live_vector_p (struct mem_node *m, void *p)
       while (VECTOR_IN_BLOCK (vector, block)
             && vector <= (struct Lisp_Vector *) p)
        {
-         if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
-           vector = ADVANCE (vector, (vector->header.size
-                                      & PSEUDOVECTOR_SIZE_MASK));
-         else if (vector == p)
+         if (!PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) && vector == p)
            return 1;
          else
-           vector = ADVANCE (vector, vector->header.next.nbytes);
+           vector = ADVANCE (vector, vector_nbytes (vector));
        }
     }
-  else if (m->type == MEM_TYPE_VECTORLIKE && p == m->start)
+  else if (m->type == MEM_TYPE_VECTORLIKE
+          && (char *) p == ((char *) m->start
+                            + offsetof (struct large_vector, v)))
     /* This memory node corresponds to a large vector.  */
     return 1;
   return 0;
@@ -4381,11 +4507,6 @@ mark_memory (void *start, void *end)
       }
 }
 
-/* setjmp will work with GCC unless NON_SAVING_SETJMP is defined in
-   the GCC system configuration.  In gcc 3.2, the only systems for
-   which this is so are i386-sco5 non-ELF, i386-sysv3 (maybe included
-   by others?) and ns32k-pc532-min.  */
-
 #if !defined GC_SAVE_REGISTERS_ON_STACK && !defined GC_SETJMP_WORKS
 
 static bool setjmp_tested_p;
@@ -4644,7 +4765,7 @@ valid_pointer_p (void *p)
      Unfortunately, we cannot use NULL_DEVICE here, as emacs_write may
      not validate p in that case.  */
 
-  if (pipe (fd) == 0)
+  if (emacs_pipe (fd) == 0)
     {
       bool valid = emacs_write (fd[1], (char *) p, 16) == 16;
       emacs_close (fd[1]);
@@ -4656,12 +4777,12 @@ valid_pointer_p (void *p)
 #endif
 }
 
-/* Return 2 if OBJ is a killed or special buffer object.
-   Return 1 if OBJ is a valid lisp object.
-   Return 0 if OBJ is NOT a valid lisp object.
-   Return -1 if we cannot validate OBJ.
-   This function can be quite slow,
-   so it should only be used in code for manual debugging.  */
+/* Return 2 if OBJ is a killed or special buffer object, 1 if OBJ is a
+   valid lisp object, 0 if OBJ is NOT a valid lisp object, or -1 if we
+   cannot validate OBJ.  This function can be quite slow, so its primary
+   use is the manual debugging.  The only exception is print_object, where
+   we use it to check whether the memory referenced by the pointer of
+   Lisp_Save_Value object contains valid objects.  */
 
 int
 valid_lisp_object_p (Lisp_Object obj)
@@ -5028,9 +5149,9 @@ Does not copy symbols.  Copies strings without text properties.  */)
 void
 staticpro (Lisp_Object *varaddress)
 {
-  staticvec[staticidx++] = varaddress;
   if (staticidx >= NSTATICS)
     fatal ("NSTATICS too small; try increasing and recompiling Emacs.");
+  staticvec[staticidx++] = varaddress;
 }
 
 \f
@@ -5092,7 +5213,6 @@ returns nil, because real GC can't be done.
 See Info node `(elisp)Garbage Collection'.  */)
   (void)
 {
-  struct specbinding *bind;
   struct buffer *nextb;
   char stack_top_variable;
   ptrdiff_t i;
@@ -5101,7 +5221,6 @@ See Info node `(elisp)Garbage Collection'.  */)
   EMACS_TIME start;
   Lisp_Object retval = Qnil;
   size_t tot_before = 0;
-  struct backtrace backtrace;
 
   if (abort_on_gc)
     emacs_abort ();
@@ -5112,12 +5231,7 @@ See Info node `(elisp)Garbage Collection'.  */)
     return Qnil;
 
   /* Record this function, so it appears on the profiler's backtraces.  */
-  backtrace.next = backtrace_list;
-  backtrace.function = Qautomatic_gc;
-  backtrace.args = &Qnil;
-  backtrace.nargs = 0;
-  backtrace.debug_on_exit = 0;
-  backtrace_list = &backtrace;
+  record_in_backtrace (Qautomatic_gc, &Qnil, 0);
 
   check_cons_list ();
 
@@ -5137,7 +5251,7 @@ See Info node `(elisp)Garbage Collection'.  */)
 
   /* Save what's currently displayed in the echo area.  */
   message_p = push_message ();
-  record_unwind_protect (pop_message_unwind, Qnil);
+  record_unwind_protect_void (pop_message_unwind);
 
   /* Save a copy of the contents of the stack, for debugging.  */
 #if MAX_SAVE_STACK > 0
@@ -5184,11 +5298,7 @@ See Info node `(elisp)Garbage Collection'.  */)
   for (i = 0; i < staticidx; i++)
     mark_object (*staticvec[i]);
 
-  for (bind = specpdl; bind != specpdl_ptr; bind++)
-    {
-      mark_object (bind->symbol);
-      mark_object (bind->old_value);
-    }
+  mark_specpdl ();
   mark_terminals ();
   mark_kboards ();
 
@@ -5222,7 +5332,6 @@ See Info node `(elisp)Garbage Collection'.  */)
       mark_object (handler->var);
     }
   }
-  mark_backtrace ();
 #endif
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -5287,12 +5396,12 @@ See Info node `(elisp)Garbage Collection'.  */)
   dump_zombies ();
 #endif
 
-  unblock_input ();
-
   check_cons_list ();
 
   gc_in_progress = 0;
 
+  unblock_input ();
+
   consing_since_gc = 0;
   if (gc_cons_threshold < GC_DEFAULT_THRESHOLD / 10)
     gc_cons_threshold = GC_DEFAULT_THRESHOLD / 10;
@@ -5344,7 +5453,8 @@ See Info node `(elisp)Garbage Collection'.  */)
     total[4] = list3 (Qstring_bytes, make_number (1),
                      bounded_number (total_string_bytes));
 
-    total[5] = list3 (Qvectors, make_number (sizeof (struct Lisp_Vector)),
+    total[5] = list3 (Qvectors,
+                     make_number (header_size + sizeof (Lisp_Object)),
                      bounded_number (total_vectors));
 
     total[6] = list4 (Qvector_slots, make_number (word_size),
@@ -5413,7 +5523,6 @@ See Info node `(elisp)Garbage Collection'.  */)
       malloc_probe (swept);
     }
 
-  backtrace_list = backtrace.next;
   return retval;
 }
 
@@ -5587,7 +5696,7 @@ mark_discard_killed_buffers (Lisp_Object list)
        {
          CONS_MARK (XCONS (tail));
          mark_object (XCAR (tail));
-         prev = &XCDR_AS_LVALUE (tail);
+         prev = xcdr_addr (tail);
        }
     }
   mark_object (tail);
@@ -5687,7 +5796,7 @@ mark_object (Lisp_Object arg)
 
        if (ptr->header.size & PSEUDOVECTOR_FLAG)
          pvectype = ((ptr->header.size & PVEC_TYPE_MASK)
-                     >> PSEUDOVECTOR_SIZE_BITS);
+                     >> PSEUDOVECTOR_AREA_BITS);
        else
          pvectype = PVEC_NORMAL_VECTOR;
 
@@ -5737,14 +5846,13 @@ mark_object (Lisp_Object arg)
          case PVEC_WINDOW:
            {
              struct window *w = (struct window *) ptr;
-             bool leaf = NILP (w->hchild) && NILP (w->vchild);
 
              mark_vectorlike (ptr);
 
-             /* Mark glyphs for leaf windows.  Marking window
+             /* Mark glyph matrices, if any.  Marking window
                 matrices is sufficient because frame matrices
                 use the same glyph memory.  */
-             if (leaf && w->current_matrix)
+             if (w->current_matrix)
                {
                  mark_glyph_matrix (w->current_matrix);
                  mark_glyph_matrix (w->desired_matrix);
@@ -5766,6 +5874,9 @@ mark_object (Lisp_Object arg)
              struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr;
 
              mark_vectorlike (ptr);
+             mark_object (h->test.name);
+             mark_object (h->test.user_hash_function);
+             mark_object (h->test.user_cmp_function);
              /* If hash table is not weak, mark all keys and values.
                 For weak tables, mark only the vector.  */
              if (NILP (h->weak))
@@ -5872,20 +5983,27 @@ mark_object (Lisp_Object arg)
 
        case Lisp_Misc_Save_Value:
          XMISCANY (obj)->gcmarkbit = 1;
-#if GC_MARK_STACK
          {
-           register struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj);
-           /* If DOGC is set, POINTER is the address of a memory
-              area containing INTEGER potential Lisp_Objects.  */
-           if (ptr->dogc)
+           struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj);
+           /* If `save_type' is zero, `data[0].pointer' is the address
+              of a memory area containing `data[1].integer' potential
+              Lisp_Objects.  */
+           if (GC_MARK_STACK && ptr->save_type == SAVE_TYPE_MEMORY)
              {
-               Lisp_Object *p = (Lisp_Object *) ptr->pointer;
+               Lisp_Object *p = ptr->data[0].pointer;
                ptrdiff_t nelt;
-               for (nelt = ptr->integer; nelt > 0; nelt--, p++)
+               for (nelt = ptr->data[1].integer; nelt > 0; nelt--, p++)
                  mark_maybe_object (*p);
              }
+           else
+             {
+               /* Find Lisp_Objects in `data[N]' slots and mark them.  */
+               int i;
+               for (i = 0; i < SAVE_VALUE_SLOTS; i++)
+                 if (save_type (ptr, i) == SAVE_OBJECT)
+                   mark_object (ptr->data[i].object);
+             }
          }
-#endif
          break;
 
        case Lisp_Misc_Overlay:
@@ -6317,7 +6435,7 @@ gc_sweep (void)
     for (buffer = all_buffers; buffer; buffer = *bprev)
       if (!VECTOR_MARKED_P (buffer))
        {
-         *bprev = buffer->header.next.buffer;
+         *bprev = buffer->next;
          lisp_free (buffer);
        }
       else
@@ -6326,7 +6444,7 @@ gc_sweep (void)
          /* Do not use buffer_(set|get)_intervals here.  */
          buffer->text->intervals = balance_intervals (buffer->text->intervals);
          total_buffers++;
-         bprev = &buffer->header.next.buffer;
+         bprev = &buffer->next;
        }
   }
 
@@ -6435,13 +6553,13 @@ bool suppress_checking;
 void
 die (const char *msg, const char *file, int line)
 {
-  fprintf (stderr, "\r\n%s:%d: Emacs fatal error: %s\r\n",
+  fprintf (stderr, "\r\n%s:%d: Emacs fatal error: assertion failed: %s\r\n",
           file, line, msg);
   terminate_due_to_signal (SIGABRT, INT_MAX);
 }
 #endif
 \f
-/* Initialization */
+/* Initialization */
 
 void
 init_alloc_once (void)
@@ -6456,9 +6574,9 @@ init_alloc_once (void)
 #endif
 
 #ifdef DOUG_LEA_MALLOC
-  mallopt (M_TRIM_THRESHOLD, 128*1024); /* trim threshold */
-  mallopt (M_MMAP_THRESHOLD, 64*1024); /* mmap threshold */
-  mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); /* max. number of mmap'ed areas */
+  mallopt (M_TRIM_THRESHOLD, 128 * 1024); /* Trim threshold.  */
+  mallopt (M_MMAP_THRESHOLD, 64 * 1024);  /* Mmap threshold.  */
+  mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);   /* Max. number of mmap'ed areas.  */
 #endif
   init_strings ();
   init_vectors ();
@@ -6620,8 +6738,5 @@ union
   enum MAX_ALLOCA MAX_ALLOCA;
   enum More_Lisp_Bits More_Lisp_Bits;
   enum pvec_type pvec_type;
-#if USE_LSB_TAG
-  enum lsb_bits lsb_bits;
-#endif
 } const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0};
 #endif /* __GNUC__ */