Merge from emacs-24; up to 2014-03-23T23:14:52Z!yamaoka@jpl.org
[bpt/emacs.git] / src / alloc.c
index 1124574..e5cd5fe 100644 (file)
@@ -1,6 +1,6 @@
 /* Storage allocation and gc for GNU Emacs Lisp interpreter.
 
-Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2013 Free Software
+Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2014 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -20,8 +20,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
-#define LISP_INLINE EXTERN_INLINE
-
 #include <stdio.h>
 #include <limits.h>            /* For CHAR_BIT.  */
 
@@ -44,9 +42,24 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "frame.h"
 #include "blockinput.h"
 #include "termhooks.h"         /* For struct terminal.  */
+#ifdef HAVE_WINDOW_SYSTEM
+#include TERM_HEADER
+#endif /* HAVE_WINDOW_SYSTEM */
 
 #include <verify.h>
 
+#if (defined ENABLE_CHECKING                   \
+     && defined HAVE_VALGRIND_VALGRIND_H       \
+     && !defined USE_VALGRIND)
+# define USE_VALGRIND 1
+#endif
+
+#if USE_VALGRIND
+#include <valgrind/valgrind.h>
+#include <valgrind/memcheck.h>
+static bool valgrind_p;
+#endif
+
 /* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects.
    Doable only if GC_MARK_STACK.  */
 #if ! GC_MARK_STACK
@@ -190,7 +203,27 @@ const char *pending_malloc_warning;
 #if MAX_SAVE_STACK > 0
 static char *stack_copy;
 static ptrdiff_t stack_copy_size;
-#endif
+
+/* Copy to DEST a block of memory from SRC of size SIZE bytes,
+   avoiding any address sanitization.  */
+
+static void * ATTRIBUTE_NO_SANITIZE_ADDRESS
+no_sanitize_memcpy (void *dest, void const *src, size_t size)
+{
+  if (! ADDRESS_SANITIZER)
+    return memcpy (dest, src, size);
+  else
+    {
+      size_t i;
+      char *d = dest;
+      char const *s = src;
+      for (i = 0; i < size; i++)
+       d[i] = s[i];
+      return dest;
+    }
+}
+
+#endif /* MAX_SAVE_STACK > 0 */
 
 static Lisp_Object Qconses;
 static Lisp_Object Qsymbols;
@@ -318,7 +351,6 @@ static void *min_heap_address, *max_heap_address;
 static struct mem_node mem_z;
 #define MEM_NIL &mem_z
 
-#if GC_MARK_STACK || defined GC_MALLOC_CHECK
 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 *);
@@ -326,7 +358,6 @@ static void mem_rotate_right (struct mem_node *);
 static void mem_delete (struct mem_node *);
 static void mem_delete_fixup (struct mem_node *);
 static struct mem_node *mem_find (void *);
-#endif
 
 #endif /* GC_MARK_STACK || GC_MALLOC_CHECK */
 
@@ -341,7 +372,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.  */
@@ -350,13 +381,21 @@ static int staticidx;
 
 static void *pure_alloc (size_t, int);
 
+/* Return X rounded to the next multiple of Y.  Arguments should not
+   have side effects, as they are evaluated more than once.  Assume X
+   + Y - 1 does not overflow.  Tune for Y being a power of 2.  */
 
-/* Value is SZ rounded up to the next multiple of ALIGNMENT.
-   ALIGNMENT must be a power of 2.  */
+#define ROUNDUP(x, y) ((y) & ((y) - 1)                                 \
+                      ? ((x) + (y) - 1) - ((x) + (y) - 1) % (y)        \
+                      : ((x) + (y) - 1) & ~ ((y) - 1))
 
-#define ALIGN(ptr, ALIGNMENT) \
-  ((void *) (((uintptr_t) (ptr) + (ALIGNMENT) - 1) \
-            & ~ ((ALIGNMENT) - 1)))
+/* Return PTR rounded up to the next multiple of ALIGNMENT.  */
+
+static void *
+ALIGN (void *ptr, int alignment)
+{
+  return (void *) ROUNDUP ((uintptr_t) ptr, alignment);
+}
 
 static void
 XFLOAT_INIT (Lisp_Object f, double n)
@@ -364,6 +403,23 @@ XFLOAT_INIT (Lisp_Object f, double n)
   XFLOAT (f)->u.data = n;
 }
 
+static bool
+pointers_fit_in_lispobj_p (void)
+{
+  return (UINTPTR_MAX <= VAL_MAX) || USE_LSB_TAG;
+}
+
+static bool
+mmap_lisp_allowed_p (void)
+{
+  /* If we can't store all memory addresses in our lisp objects, it's
+     risky to let the heap use mmap and give us addresses from all
+     over our address space.  We also can't use mmap for lisp objects
+     if we might dump: unexec doesn't preserve the contents of mmaped
+     regions.  */
+  return pointers_fit_in_lispobj_p () && !might_dump;
+}
+
 \f
 /************************************************************************
                                Malloc
@@ -796,12 +852,35 @@ 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 above, but duplicates Lisp string to C string.  */
+
+char *
+xlispstrdup (Lisp_Object string)
+{
+  ptrdiff_t size = SBYTES (string) + 1;
+  return memcpy (xmalloc (size), SSDATA (string), size);
 }
 
+/* Assign to *PTR a copy of STRING, freeing any storage *PTR formerly
+   pointed to.  If STRING is null, assign it without copying anything.
+   Allocate before freeing, to avoid a dangling pointer if allocation
+   fails.  */
+
+void
+dupstring (char **ptr, char const *string)
+{
+  char *old = *ptr;
+  *ptr = string ? xstrdup (string) : 0;
+  xfree (old);
+}
+
+
 /* Like putenv, but (1) use the equivalent of xmalloc and (2) the
    argument is a const pointer.  */
 
@@ -892,8 +971,26 @@ lisp_free (void *block)
 /* The entry point is lisp_align_malloc which returns blocks of at most
    BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary.  */
 
-#if defined (HAVE_POSIX_MEMALIGN) && defined (SYSTEM_MALLOC)
-#define USE_POSIX_MEMALIGN 1
+/* Use aligned_alloc if it or a simple substitute is available.
+   Address sanitization breaks aligned allocation, as of gcc 4.8.2 and
+   clang 3.3 anyway.  */
+
+#if ! ADDRESS_SANITIZER
+# if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC
+#  define USE_ALIGNED_ALLOC 1
+/* Defined in gmalloc.c.  */
+void *aligned_alloc (size_t, size_t);
+# elif defined HAVE_ALIGNED_ALLOC
+#  define USE_ALIGNED_ALLOC 1
+# elif defined HAVE_POSIX_MEMALIGN
+#  define USE_ALIGNED_ALLOC 1
+static void *
+aligned_alloc (size_t alignment, size_t size)
+{
+  void *p;
+  return posix_memalign (&p, alignment, size) == 0 ? p : 0;
+}
+# endif
 #endif
 
 /* BLOCK_ALIGN has to be a power of 2.  */
@@ -903,7 +1000,7 @@ lisp_free (void *block)
    malloc a chance to minimize the amount of memory wasted to alignment.
    It should be tuned to the particular malloc library used.
    On glibc-2.3.2, malloc never tries to align, so a padding of 0 is best.
-   posix_memalign on the other hand would ideally prefer a value of 4
+   aligned_alloc on the other hand would ideally prefer a value of 4
    because otherwise, there's 1020 bytes wasted between each ablocks.
    In Emacs, testing shows that those 1020 can most of the time be
    efficiently used by malloc to place other objects, so a value of 0 can
@@ -948,7 +1045,7 @@ struct ablocks
   struct ablock blocks[ABLOCKS_SIZE];
 };
 
-/* Size of the block requested from malloc or posix_memalign.  */
+/* Size of the block requested from malloc or aligned_alloc.  */
 #define ABLOCKS_BYTES (sizeof (struct ablocks) - BLOCK_PADDING)
 
 #define ABLOCK_ABASE(block) \
@@ -960,11 +1057,11 @@ struct ablocks
 #define ABLOCKS_BUSY(abase) ((abase)->blocks[0].abase)
 
 /* Pointer to the (not necessarily aligned) malloc block.  */
-#ifdef USE_POSIX_MEMALIGN
+#ifdef USE_ALIGNED_ALLOC
 #define ABLOCKS_BASE(abase) (abase)
 #else
 #define ABLOCKS_BASE(abase) \
-  (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void**)abase)[-1])
+  (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **)abase)[-1])
 #endif
 
 /* The list of free ablock.   */
@@ -993,19 +1090,12 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
       intptr_t aligned; /* int gets warning casting to 64-bit pointer.  */
 
 #ifdef DOUG_LEA_MALLOC
-      /* Prevent mmap'ing the chunk.  Lisp data may not be mmap'ed
-        because mapped region contents are not preserved in
-        a dumped Emacs.  */
-      mallopt (M_MMAP_MAX, 0);
+      if (!mmap_lisp_allowed_p ())
+        mallopt (M_MMAP_MAX, 0);
 #endif
 
-#ifdef USE_POSIX_MEMALIGN
-      {
-       int err = posix_memalign (&base, BLOCK_ALIGN, ABLOCKS_BYTES);
-       if (err)
-         base = NULL;
-       abase = base;
-      }
+#ifdef USE_ALIGNED_ALLOC
+      abase = base = aligned_alloc (BLOCK_ALIGN, ABLOCKS_BYTES);
 #else
       base = malloc (ABLOCKS_BYTES);
       abase = ALIGN (base, BLOCK_ALIGN);
@@ -1019,11 +1109,11 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
 
       aligned = (base == abase);
       if (!aligned)
-       ((void**)abase)[-1] = base;
+       ((void **) abase)[-1] = base;
 
 #ifdef DOUG_LEA_MALLOC
-      /* Back to a reasonable maximum of mmap'ed areas.  */
-      mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
+      if (!mmap_lisp_allowed_p ())
+          mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
 #endif
 
 #if ! USE_LSB_TAG
@@ -1063,8 +1153,8 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
     }
 
   abase = ABLOCK_ABASE (free_ablock);
-  ABLOCKS_BUSY (abase) =
-    (struct ablocks *) (2 + (intptr_t) ABLOCKS_BUSY (abase));
+  ABLOCKS_BUSY (abase)
+    (struct ablocks *) (2 + (intptr_t) ABLOCKS_BUSY (abase));
   val = free_ablock;
   free_ablock = free_ablock->x.next_free;
 
@@ -1260,28 +1350,32 @@ mark_interval (register INTERVAL i, Lisp_Object dummy)
 
 #define LARGE_STRING_BYTES 1024
 
-/* Struct or union describing string memory sub-allocated from an sblock.
-   This is where the contents of Lisp strings are stored.  */
-
-#ifdef GC_CHECK_STRING_BYTES
+/* The SDATA typedef is a struct or union describing string memory
+   sub-allocated from an sblock.  This is where the contents of Lisp
+   strings are stored.  */
 
-typedef struct
+struct sdata
 {
   /* Back-pointer to the string this sdata belongs to.  If null, this
-     structure is free, and the NBYTES member of the union below
+     structure is free, and NBYTES (in this structure or in the union below)
      contains the string's byte size (the same value that STRING_BYTES
      would return if STRING were non-null).  If non-null, STRING_BYTES
      (STRING) is the size of the data, and DATA contains the string's
      contents.  */
   struct Lisp_String *string;
 
+#ifdef GC_CHECK_STRING_BYTES
   ptrdiff_t nbytes;
+#endif
+
   unsigned char data[FLEXIBLE_ARRAY_MEMBER];
-} sdata;
+};
+
+#ifdef GC_CHECK_STRING_BYTES
 
+typedef struct sdata sdata;
 #define SDATA_NBYTES(S)        (S)->nbytes
 #define SDATA_DATA(S)  (S)->data
-#define SDATA_SELECTOR(member) member
 
 #else
 
@@ -1289,12 +1383,16 @@ typedef union
 {
   struct Lisp_String *string;
 
-  /* When STRING is non-null.  */
-  struct
-  {
-    struct Lisp_String *string;
-    unsigned char data[FLEXIBLE_ARRAY_MEMBER];
-  } u;
+  /* When STRING is nonnull, this union is actually of type 'struct sdata',
+     which has a flexible array member.  However, if implemented by
+     giving this union a member of type 'struct sdata', the union
+     could not be the last (flexible) member of 'struct sblock',
+     because C99 prohibits a flexible array member from having a type
+     that is itself a flexible array.  So, comment this member out here,
+     but remember that the option's there when using this union.  */
+#if 0
+  struct sdata u;
+#endif
 
   /* When STRING is null.  */
   struct
@@ -1305,13 +1403,11 @@ typedef union
 } sdata;
 
 #define SDATA_NBYTES(S)        (S)->n.nbytes
-#define SDATA_DATA(S)  (S)->u.data
-#define SDATA_SELECTOR(member) u.member
+#define SDATA_DATA(S)  ((struct sdata *) (S))->data
 
 #endif /* not GC_CHECK_STRING_BYTES */
 
-#define SDATA_DATA_OFFSET offsetof (sdata, SDATA_SELECTOR (data))
-
+enum { SDATA_DATA_OFFSET = offsetof (struct sdata, data) };
 
 /* Structure describing a block of memory which is sub-allocated to
    obtain string data memory for strings.  Blocks for small strings
@@ -1327,8 +1423,8 @@ struct sblock
      of the sblock if there isn't any space left in this block.  */
   sdata *next_free;
 
-  /* Start of data.  */
-  sdata first_data;
+  /* String data.  */
+  sdata data[FLEXIBLE_ARRAY_MEMBER];
 };
 
 /* Number of Lisp strings in a string_block structure.  The 1020 is
@@ -1444,7 +1540,7 @@ static ptrdiff_t const STRING_BYTES_MAX =
   min (STRING_BYTES_BOUND,
        ((SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD
         - GC_STRING_EXTRA
-        - offsetof (struct sblock, first_data)
+        - offsetof (struct sblock, data)
         - SDATA_DATA_OFFSET)
        & ~(sizeof (EMACS_INT) - 1)));
 
@@ -1487,7 +1583,7 @@ check_sblock (struct sblock *b)
 
   end = b->next_free;
 
-  for (from = &b->first_data; from < end; from = from_end)
+  for (from = b->data; from < end; from = from_end)
     {
       /* Compute the next FROM here because copying below may
         overwrite data we need to compute it.  */
@@ -1515,7 +1611,7 @@ check_string_bytes (bool all_p)
 
       for (b = large_sblocks; b; b = b->next)
        {
-         struct Lisp_String *s = b->first_data.string;
+         struct Lisp_String *s = b->data[0].string;
          if (s)
            string_bytes (s);
        }
@@ -1649,30 +1745,22 @@ allocate_string_data (struct Lisp_String *s,
 
   if (nbytes > LARGE_STRING_BYTES)
     {
-      size_t size = offsetof (struct sblock, first_data) + needed;
+      size_t size = offsetof (struct sblock, data) + needed;
 
 #ifdef DOUG_LEA_MALLOC
-      /* Prevent mmap'ing the chunk.  Lisp data may not be mmap'ed
-        because mapped region contents are not preserved in
-        a dumped Emacs.
-
-         In case you think of allowing it in a dumped Emacs at the
-         cost of not being able to re-dump, there's another reason:
-         mmap'ed data typically have an address towards the top of the
-         address space, which won't fit into an EMACS_INT (at least on
-         32-bit systems with the current tagging scheme).  --fx  */
-      mallopt (M_MMAP_MAX, 0);
+      if (!mmap_lisp_allowed_p ())
+        mallopt (M_MMAP_MAX, 0);
 #endif
 
       b = lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP);
 
 #ifdef DOUG_LEA_MALLOC
-      /* Back to a reasonable maximum of mmap'ed areas.  */
-      mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
+      if (!mmap_lisp_allowed_p ())
+        mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
 #endif
 
-      b->next_free = &b->first_data;
-      b->first_data.string = NULL;
+      b->next_free = b->data;
+      b->data[0].string = NULL;
       b->next = large_sblocks;
       large_sblocks = b;
     }
@@ -1683,8 +1771,8 @@ allocate_string_data (struct Lisp_String *s,
     {
       /* Not enough room in the current sblock.  */
       b = lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP);
-      b->next_free = &b->first_data;
-      b->first_data.string = NULL;
+      b->next_free = b->data;
+      b->data[0].string = NULL;
       b->next = NULL;
 
       if (current_sblock)
@@ -1729,6 +1817,7 @@ allocate_string_data (struct Lisp_String *s,
 
 /* Sweep and compact strings.  */
 
+NO_INLINE /* For better stack traces */
 static void
 sweep_strings (void)
 {
@@ -1838,7 +1927,7 @@ free_large_strings (void)
     {
       next = b->next;
 
-      if (b->first_data.string == NULL)
+      if (b->data[0].string == NULL)
        lisp_free (b);
       else
        {
@@ -1865,7 +1954,7 @@ compact_small_strings (void)
      to, and TB_END is the end of TB.  */
   tb = oldest_sblock;
   tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE);
-  to = &tb->first_data;
+  to = tb->data;
 
   /* Step through the blocks from the oldest to the youngest.  We
      expect that old blocks will stabilize over time, so that less
@@ -1875,7 +1964,7 @@ compact_small_strings (void)
       end = b->next_free;
       eassert ((char *) end <= (char *) b + SBLOCK_SIZE);
 
-      for (from = &b->first_data; from < end; from = from_end)
+      for (from = b->data; from < end; from = from_end)
        {
          /* Compute the next FROM here because copying below may
             overwrite data we need to compute it.  */
@@ -1912,7 +2001,7 @@ compact_small_strings (void)
                  tb->next_free = to;
                  tb = tb->next;
                  tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE);
-                 to = &tb->first_data;
+                 to = tb->data;
                  to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA);
                }
 
@@ -1956,7 +2045,6 @@ INIT must be an integer that represents a character.  */)
   (Lisp_Object length, Lisp_Object init)
 {
   register Lisp_Object val;
-  register unsigned char *p, *end;
   int c;
   EMACS_INT nbytes;
 
@@ -1968,74 +2056,92 @@ INIT must be an integer that represents a character.  */)
     {
       nbytes = XINT (length);
       val = make_uninit_string (nbytes);
-      p = SDATA (val);
-      end = p + SCHARS (val);
-      while (p != end)
-       *p++ = c;
+      memset (SDATA (val), c, nbytes);
+      SDATA (val)[nbytes] = 0;
     }
   else
     {
       unsigned char str[MAX_MULTIBYTE_LENGTH];
-      int len = CHAR_STRING (c, str);
+      ptrdiff_t len = CHAR_STRING (c, str);
       EMACS_INT string_len = XINT (length);
+      unsigned char *p, *beg, *end;
 
       if (string_len > STRING_BYTES_MAX / len)
        string_overflow ();
       nbytes = len * string_len;
       val = make_uninit_multibyte_string (string_len, nbytes);
-      p = SDATA (val);
-      end = p + nbytes;
-      while (p != end)
+      for (beg = SDATA (val), p = beg, end = beg + nbytes; p < end; p += len)
        {
-         memcpy (p, str, len);
-         p += len;
+         /* First time we just copy `str' to the data of `val'.  */
+         if (p == beg)
+           memcpy (p, str, len);
+         else
+           {
+             /* Next time we copy largest possible chunk from
+                initialized to uninitialized part of `val'.  */
+             len = min (p - beg, end - p);
+             memcpy (p, beg, len);
+           }
        }
+      *p = 0;
     }
 
-  *p = 0;
   return val;
 }
 
+/* Fill A with 1 bits if INIT is non-nil, and with 0 bits otherwise.
+   Return A.  */
 
-DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0,
-       doc: /* Return a new bool-vector of length LENGTH, using INIT for each element.
-LENGTH must be a number.  INIT matters only in whether it is t or nil.  */)
-  (Lisp_Object length, Lisp_Object init)
+Lisp_Object
+bool_vector_fill (Lisp_Object a, Lisp_Object init)
 {
-  register Lisp_Object val;
-  struct Lisp_Bool_Vector *p;
-  ptrdiff_t length_in_chars;
-  EMACS_INT length_in_elts;
-  int bits_per_value;
-  int extra_bool_elts = ((bool_header_size - header_size + word_size - 1)
-                        / word_size);
-
-  CHECK_NATNUM (length);
-
-  bits_per_value = sizeof (EMACS_INT) * BOOL_VECTOR_BITS_PER_CHAR;
-
-  length_in_elts = (XFASTINT (length) + bits_per_value - 1) / bits_per_value;
+  EMACS_INT nbits = bool_vector_size (a);
+  if (0 < nbits)
+    {
+      unsigned char *data = bool_vector_uchar_data (a);
+      int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1;
+      ptrdiff_t nbytes = bool_vector_bytes (nbits);
+      int last_mask = ~ (~0 << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1));
+      memset (data, pattern, nbytes - 1);
+      data[nbytes - 1] = pattern & last_mask;
+    }
+  return a;
+}
 
-  val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil);
+/* Return a newly allocated, uninitialized bool vector of size NBITS.  */
 
-  /* No Lisp_Object to trace in there.  */
+Lisp_Object
+make_uninit_bool_vector (EMACS_INT nbits)
+{
+  Lisp_Object val;
+  EMACS_INT words = bool_vector_words (nbits);
+  EMACS_INT word_bytes = words * sizeof (bits_word);
+  EMACS_INT needed_elements = ((bool_header_size - header_size + word_bytes
+                               + word_size - 1)
+                              / word_size);
+  struct Lisp_Bool_Vector *p
+    = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements);
+  XSETVECTOR (val, p);
   XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0);
+  p->size = nbits;
 
-  p = XBOOL_VECTOR (val);
-  p->size = XFASTINT (length);
+  /* Clear padding at the end.  */
+  if (words)
+    p->data[words - 1] = 0;
 
-  length_in_chars = ((XFASTINT (length) + BOOL_VECTOR_BITS_PER_CHAR - 1)
-                    / BOOL_VECTOR_BITS_PER_CHAR);
-  if (length_in_chars)
-    {
-      memset (p->data, ! NILP (init) ? -1 : 0, length_in_chars);
+  return val;
+}
 
-      /* Clear any extraneous bits in the last byte.  */
-      p->data[length_in_chars - 1]
-       &= (1 << ((XFASTINT (length) - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)) - 1;
-    }
+DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0,
+       doc: /* Return a new bool-vector of length LENGTH, using INIT for each element.
+LENGTH must be a number.  INIT matters only in whether it is t or nil.  */)
+  (Lisp_Object length, Lisp_Object init)
+{
+  Lisp_Object val;
 
-  return val;
+  CHECK_NATNUM (length);
+  val = make_uninit_bool_vector (XFASTINT (length));
+  return bool_vector_fill (val, init);
 }
 
 
@@ -2548,36 +2654,53 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0,
                           Vector Allocation
  ***********************************************************************/
 
+/* Sometimes a vector's contents are merely a pointer internally used
+   in vector allocation code.  Usually you don't want to touch this.  */
+
+static struct Lisp_Vector *
+next_vector (struct Lisp_Vector *v)
+{
+  return XUNTAG (v->contents[0], 0);
+}
+
+static void
+set_next_vector (struct Lisp_Vector *v, struct Lisp_Vector *p)
+{
+  v->contents[0] = make_lisp_ptr (p, 0);
+}
+
 /* This value is balanced well enough to avoid too much internal overhead
    for the most common cases; it's not required to be a power of two, but
    it's expected to be a mult-of-ROUNDUP_SIZE (see below).  */
 
 #define VECTOR_BLOCK_SIZE 4096
 
-/* Align allocation request sizes to be a multiple of ROUNDUP_SIZE.  */
 enum
   {
-    roundup_size = COMMON_MULTIPLE (word_size, USE_LSB_TAG ? GCALIGNMENT : 1)
-  };
+    /* Alignment of struct Lisp_Vector objects.  */
+    vector_alignment = COMMON_MULTIPLE (ALIGNOF_STRUCT_LISP_VECTOR,
+                                       USE_LSB_TAG ? GCALIGNMENT : 1),
 
-/* ROUNDUP_SIZE must be a power of 2.  */
-verify ((roundup_size & (roundup_size - 1)) == 0);
+    /* Vector size requests are a multiple of this.  */
+    roundup_size = COMMON_MULTIPLE (vector_alignment, word_size)
+  };
 
 /* Verify assumptions described above.  */
 verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0);
 verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
 
-/* Round up X to nearest mult-of-ROUNDUP_SIZE.  */
-
-#define vroundup(x) (((x) + (roundup_size - 1)) & ~(roundup_size - 1))
+/* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time.  */
+#define vroundup_ct(x) ROUNDUP (x, roundup_size)
+/* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at runtime.  */
+#define vroundup(x) (eassume ((x) >= 0), vroundup_ct (x))
 
 /* Rounding helps to maintain alignment constraints if USE_LSB_TAG.  */
 
-#define VECTOR_BLOCK_BYTES (VECTOR_BLOCK_SIZE - vroundup (sizeof (void *)))
+#define VECTOR_BLOCK_BYTES (VECTOR_BLOCK_SIZE - vroundup_ct (sizeof (void *)))
 
 /* Size of the minimal vector allocated from block.  */
 
-#define VBLOCK_BYTES_MIN vroundup (header_size + sizeof (Lisp_Object))
+#define VBLOCK_BYTES_MIN vroundup_ct (header_size + sizeof (Lisp_Object))
 
 /* Size of the largest vector allocated from block.  */
 
@@ -2598,22 +2721,6 @@ 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, tmp)             \
@@ -2623,26 +2730,37 @@ set_next_in_free_list (struct Lisp_Vector *v, struct Lisp_Vector *next)
     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]); \
+    set_next_vector (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.  */
+   which are allocated at their own, e.g. outside of vector blocks.
+
+   struct large_vector itself cannot contain a struct Lisp_Vector, as
+   the latter contains a flexible array member and C99 does not allow
+   such structs to be nested.  Instead, each struct large_vector
+   object LV is followed by a struct Lisp_Vector, which is at offset
+   large_vector_offset from LV, and whose address is therefore
+   large_vector_vec (&LV).  */
 
 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;
+  struct large_vector *next;
+};
+
+enum
+{
+  large_vector_offset = ROUNDUP (sizeof (struct large_vector), vector_alignment)
 };
 
+static struct Lisp_Vector *
+large_vector_vec (struct large_vector *p)
+{
+  return (struct Lisp_Vector *) ((char *) p + large_vector_offset);
+}
+
 /* This internal type is used to maintain an underlying storage
    for small vectors.  */
 
@@ -2720,7 +2838,7 @@ allocate_vector_from_block (size_t nbytes)
   if (vector_free_lists[index])
     {
       vector = vector_free_lists[index];
-      vector_free_lists[index] = next_in_free_list (vector);
+      vector_free_lists[index] = next_vector (vector);
       total_free_vector_slots -= nbytes / word_size;
       return vector;
     }
@@ -2734,7 +2852,7 @@ allocate_vector_from_block (size_t nbytes)
       {
        /* This vector is larger than requested.  */
        vector = vector_free_lists[index];
-       vector_free_lists[index] = next_in_free_list (vector);
+       vector_free_lists[index] = next_vector (vector);
        total_free_vector_slots -= nbytes / word_size;
 
        /* Excess bytes are used for the smaller vector,
@@ -2774,31 +2892,53 @@ static ptrdiff_t
 vector_nbytes (struct Lisp_Vector *v)
 {
   ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG;
+  ptrdiff_t nwords;
 
   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);
+        {
+          struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v;
+         ptrdiff_t word_bytes = (bool_vector_words (bv->size)
+                                 * sizeof (bits_word));
+         ptrdiff_t boolvec_bytes = bool_header_size + word_bytes;
+         verify (header_size <= bool_header_size);
+         nwords = (boolvec_bytes - header_size + word_size - 1) / word_size;
+        }
       else
-       size = (header_size
-               + ((size & PSEUDOVECTOR_SIZE_MASK)
-                  + ((size & PSEUDOVECTOR_REST_MASK)
-                     >> PSEUDOVECTOR_SIZE_BITS)) * word_size);
+       nwords = ((size & PSEUDOVECTOR_SIZE_MASK)
+                 + ((size & PSEUDOVECTOR_REST_MASK)
+                    >> PSEUDOVECTOR_SIZE_BITS));
     }
   else
-    size = header_size + size * word_size;
-  return vroundup (size);
+    nwords = size;
+  return vroundup (header_size + word_size * nwords);
+}
+
+/* Release extra resources still in use by VECTOR, which may be any
+   vector-like object.  For now, this is used just to free data in
+   font objects.  */
+
+static void
+cleanup_vector (struct Lisp_Vector *vector)
+{
+  if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT)
+      && ((vector->header.size & PSEUDOVECTOR_SIZE_MASK)
+         == FONT_OBJECT_MAX))
+    {
+      /* Attempt to catch subtle bugs like Bug#16140.  */
+      eassert (valid_font_driver (((struct font *) vector)->driver));
+      ((struct font *) vector)->driver->close ((struct font *) vector);
+    }
 }
 
 /* Reclaim space used by unmarked vectors.  */
 
+NO_INLINE /* For better stack traces */
 static void
 sweep_vectors (void)
 {
-  struct vector_block *block = vector_blocks, **bprev = &vector_blocks;
+  struct vector_block *block, **bprev = &vector_blocks;
   struct large_vector *lv, **lvprev = &large_vectors;
   struct Lisp_Vector *vector, *next;
 
@@ -2827,6 +2967,7 @@ sweep_vectors (void)
            {
              ptrdiff_t total_bytes;
 
+             cleanup_vector (vector);
              nbytes = vector_nbytes (vector);
              total_bytes = nbytes;
              next = ADVANCE (vector, nbytes);
@@ -2838,6 +2979,7 @@ sweep_vectors (void)
                {
                  if (VECTOR_MARKED_P (next))
                    break;
+                 cleanup_vector (next);
                  nbytes = vector_nbytes (next);
                  total_bytes += nbytes;
                  next = ADVANCE (next, nbytes);
@@ -2847,12 +2989,12 @@ sweep_vectors (void)
 
              if (vector == (struct Lisp_Vector *) block->data
                  && !VECTOR_IN_BLOCK (next, block))
-               /* This block should be freed because all of it's
+               /* This block should be freed because all of its
                   space was coalesced into the only free vector.  */
                free_this_block = 1;
              else
                {
-                 int tmp;
+                 size_t tmp;
                  SETUP_ON_FREE_LIST (vector, total_bytes, tmp);
                }
            }
@@ -2874,33 +3016,27 @@ sweep_vectors (void)
 
   for (lv = large_vectors; lv; lv = *lvprev)
     {
-      vector = &lv->v;
+      vector = large_vector_vec (lv);
       if (VECTOR_MARKED_P (vector))
        {
          VECTOR_UNMARK (vector);
          total_vectors++;
          if (vector->header.size & PSEUDOVECTOR_FLAG)
            {
-             struct Lisp_Bool_Vector *b = (struct Lisp_Bool_Vector *) vector;
-
              /* All non-bool pseudovectors are small enough to be allocated
                 from vector blocks.  This code should be redesigned if some
                 pseudovector type grows beyond VBLOCK_BYTES_MAX.  */
              eassert (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR));
-
-             total_vector_slots
-               += (bool_header_size
-                   + ((b->size + BOOL_VECTOR_BITS_PER_CHAR - 1)
-                      / BOOL_VECTOR_BITS_PER_CHAR)) / word_size;
+              total_vector_slots += vector_nbytes (vector) / word_size;
            }
          else
            total_vector_slots
              += header_size / word_size + vector->header.size;
-         lvprev = &lv->next.vector;
+         lvprev = &lv->next;
        }
       else
        {
-         *lvprev = lv->next.vector;
+         *lvprev = lv->next;
          lisp_free (lv);
        }
     }
@@ -2923,10 +3059,8 @@ allocate_vectorlike (ptrdiff_t len)
       size_t nbytes = header_size + len * word_size;
 
 #ifdef DOUG_LEA_MALLOC
-      /* Prevent mmap'ing the chunk.  Lisp data may not be mmap'ed
-        because mapped region contents are not preserved in
-        a dumped Emacs.  */
-      mallopt (M_MMAP_MAX, 0);
+      if (!mmap_lisp_allowed_p ())
+        mallopt (M_MMAP_MAX, 0);
 #endif
 
       if (nbytes <= VBLOCK_BYTES_MAX)
@@ -2934,17 +3068,17 @@ allocate_vectorlike (ptrdiff_t len)
       else
        {
          struct large_vector *lv
-           = lisp_malloc ((offsetof (struct large_vector, v.contents)
+           = lisp_malloc ((large_vector_offset + header_size
                            + len * word_size),
                           MEM_TYPE_VECTORLIKE);
-         lv->next.vector = large_vectors;
+         lv->next = large_vectors;
          large_vectors = lv;
-         p = &lv->v;
+         p = large_vector_vec (lv);
        }
 
 #ifdef DOUG_LEA_MALLOC
-      /* Back to a reasonable maximum of mmap'ed areas.  */
-      mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
+      if (!mmap_lisp_allowed_p ())
+        mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
 #endif
 
       consing_since_gc += nbytes;
@@ -3101,6 +3235,9 @@ usage: (vector &rest OBJECTS)  */)
 void
 make_byte_code (struct Lisp_Vector *v)
 {
+  /* Don't allow the global zero_vector to become a byte code object.  */
+  eassert (0 < v->header.size);
+
   if (v->header.size > 1 && STRINGP (v->contents[1])
       && STRING_MULTIBYTE (v->contents[1]))
     /* BYTECODE-STRING must have been produced by Emacs 20.2 or the
@@ -3371,7 +3508,6 @@ make_save_obj_obj_obj_obj (Lisp_Object a, Lisp_Object b, Lisp_Object c,
   return val;
 }
 
-#if defined HAVE_NS || defined DOS_NT
 Lisp_Object
 make_save_ptr (void *a)
 {
@@ -3381,7 +3517,6 @@ make_save_ptr (void *a)
   p->data[0].pointer = a;
   return val;
 }
-#endif
 
 Lisp_Object
 make_save_ptr_int (void *a, ptrdiff_t b)
@@ -3394,6 +3529,19 @@ make_save_ptr_int (void *a, ptrdiff_t b)
   return val;
 }
 
+#if ! (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)
 {
@@ -3459,6 +3607,7 @@ DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
   p->charpos = 0;
   p->next = NULL;
   p->insertion_type = 0;
+  p->need_adjustment = 0;
   return val;
 }
 
@@ -3483,6 +3632,7 @@ build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos)
   m->charpos = charpos;
   m->bytepos = bytepos;
   m->insertion_type = 0;
+  m->need_adjustment = 0;
   m->next = BUF_MARKERS (buf);
   BUF_MARKERS (buf) = m;
   return obj;
@@ -3505,9 +3655,9 @@ free_marker (Lisp_Object marker)
    Any number of arguments, even zero arguments, are allowed.  */
 
 Lisp_Object
-make_event_array (register int nargs, Lisp_Object *args)
+make_event_array (ptrdiff_t nargs, Lisp_Object *args)
 {
-  int i;
+  ptrdiff_t i;
 
   for (i = 0; i < nargs; i++)
     /* The things that fit in a string
@@ -4045,7 +4195,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
@@ -4068,7 +4218,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
@@ -4094,7 +4244,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
@@ -4120,7 +4270,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
@@ -4144,7 +4294,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
@@ -4171,7 +4321,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
@@ -4188,9 +4338,7 @@ live_vector_p (struct mem_node *m, void *p)
            vector = ADVANCE (vector, vector_nbytes (vector));
        }
     }
-  else if (m->type == MEM_TYPE_VECTORLIKE
-          && (char *) p == ((char *) m->start
-                            + offsetof (struct large_vector, v)))
+  else if (m->type == MEM_TYPE_VECTORLIKE && p == large_vector_vec (m->start))
     /* This memory node corresponds to a large vector.  */
     return 1;
   return 0;
@@ -4216,8 +4364,12 @@ live_buffer_p (struct mem_node *m, void *p)
 
 #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
 
+/* Currently not used, but may be called from gdb.  */
+
+void dump_zombies (void) EXTERNALLY_VISIBLE;
+
 /* Array of objects that are kept alive because the C stack contains
-   a pattern that looks like a reference to them .  */
+   a pattern that looks like a reference to them.  */
 
 #define MAX_ZOMBIES 10
 static Lisp_Object zombies[MAX_ZOMBIES];
@@ -4272,6 +4424,11 @@ mark_maybe_object (Lisp_Object obj)
   void *po;
   struct mem_node *m;
 
+#if USE_VALGRIND
+  if (valgrind_p)
+    VALGRIND_MAKE_MEM_DEFINED (&obj, sizeof (obj));
+#endif
+
   if (INTEGERP (obj))
     return;
 
@@ -4340,6 +4497,11 @@ mark_maybe_pointer (void *p)
 {
   struct mem_node *m;
 
+#if USE_VALGRIND
+  if (valgrind_p)
+    VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p));
+#endif
+
   /* Quickly rule out some values which can't point to Lisp data.
      USE_LSB_TAG needs Lisp data to be aligned on multiples of GCALIGNMENT.
      Otherwise, assume that Lisp data is aligned on even addresses.  */
@@ -4439,16 +4601,8 @@ mark_maybe_pointer (void *p)
 /* Mark Lisp objects referenced from the address range START+OFFSET..END
    or END+OFFSET..START. */
 
-static void
+static void ATTRIBUTE_NO_SANITIZE_ADDRESS
 mark_memory (void *start, void *end)
-#if defined (__clang__) && defined (__has_feature)
-#if __has_feature(address_sanitizer)
-  /* Do not allow -faddress-sanitizer to check this function, since it
-     crosses the function stack boundary, and thus would yield many
-     false positives. */
-  __attribute__((no_address_safety_analysis))
-#endif
-#endif
 {
   void **pp;
   int i;
@@ -4598,7 +4752,7 @@ check_gcpros (void)
 
 #elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
 
-static void
+void
 dump_zombies (void)
 {
   int i;
@@ -4735,6 +4889,10 @@ mark_stack (void)
 #endif
 }
 
+#else /* GC_MARK_STACK == 0 */
+
+#define mark_maybe_object(obj) emacs_abort ()
+
 #endif /* GC_MARK_STACK != 0 */
 
 
@@ -4754,7 +4912,7 @@ valid_pointer_p (void *p)
 
   if (emacs_pipe (fd) == 0)
     {
-      bool valid = emacs_write (fd[1], (char *) p, 16) == 16;
+      bool valid = emacs_write (fd[1], p, 16) == 16;
       emacs_close (fd[1]);
       emacs_close (fd[0]);
       return valid;
@@ -5136,9 +5294,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
@@ -5183,6 +5341,102 @@ total_bytes_of_live_objects (void)
   return tot;
 }
 
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* This code has a few issues on MS-Windows, see Bug#15876 and Bug#16140.  */
+
+#if !defined (HAVE_NTGUI)
+
+/* Remove unmarked font-spec and font-entity objects from ENTRY, which is
+   (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...), and return changed entry.  */
+
+static Lisp_Object
+compact_font_cache_entry (Lisp_Object entry)
+{
+  Lisp_Object tail, *prev = &entry;
+
+  for (tail = entry; CONSP (tail); tail = XCDR (tail))
+    {
+      bool drop = 0;
+      Lisp_Object obj = XCAR (tail);
+
+      /* Consider OBJ if it is (font-spec . [font-entity font-entity ...]).  */
+      if (CONSP (obj) && FONT_SPEC_P (XCAR (obj))
+         && !VECTOR_MARKED_P (XFONT_SPEC (XCAR (obj)))
+         && VECTORP (XCDR (obj)))
+       {
+         ptrdiff_t i, size = ASIZE (XCDR (obj)) & ~ARRAY_MARK_FLAG;
+
+         /* If font-spec is not marked, most likely all font-entities
+            are not marked too.  But we must be sure that nothing is
+            marked within OBJ before we really drop it.  */
+         for (i = 0; i < size; i++)
+           if (VECTOR_MARKED_P (XFONT_ENTITY (AREF (XCDR (obj), i))))
+             break;
+
+         if (i == size)
+           drop = 1;
+       }
+      if (drop)
+       *prev = XCDR (tail);
+      else
+       prev = xcdr_addr (tail);
+    }
+  return entry;
+}
+
+#endif /* not HAVE_NTGUI */
+
+/* Compact font caches on all terminals and mark
+   everything which is still here after compaction.  */
+
+static void
+compact_font_caches (void)
+{
+  struct terminal *t;
+
+  for (t = terminal_list; t; t = t->next_terminal)
+    {
+      Lisp_Object cache = TERMINAL_FONT_CACHE (t);
+#if !defined (HAVE_NTGUI)
+      if (CONSP (cache))
+       {
+         Lisp_Object entry;
+
+         for (entry = XCDR (cache); CONSP (entry); entry = XCDR (entry))
+           XSETCAR (entry, compact_font_cache_entry (XCAR (entry)));
+       }
+#endif /* not HAVE_NTGUI */
+      mark_object (cache);
+    }
+}
+
+#else /* not HAVE_WINDOW_SYSTEM */
+
+#define compact_font_caches() (void)(0)
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
+/* Remove (MARKER . DATA) entries with unmarked MARKER
+   from buffer undo LIST and return changed list.  */
+
+static Lisp_Object
+compact_undo_list (Lisp_Object list)
+{
+  Lisp_Object tail, *prev = &list;
+
+  for (tail = list; CONSP (tail); tail = XCDR (tail))
+    {
+      if (CONSP (XCAR (tail))
+         && MARKERP (XCAR (XCAR (tail)))
+         && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit)
+       *prev = XCDR (tail);
+      else
+       prev = xcdr_addr (tail);
+    }
+  return list;
+}
+
 DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "",
        doc: /* Reclaim storage for Lisp objects no longer needed.
 Garbage collection happens automatically if you cons more than
@@ -5205,7 +5459,7 @@ See Info node `(elisp)Garbage Collection'.  */)
   ptrdiff_t i;
   bool message_p;
   ptrdiff_t count = SPECPDL_INDEX ();
-  EMACS_TIME start;
+  struct timespec start;
   Lisp_Object retval = Qnil;
   size_t tot_before = 0;
 
@@ -5230,7 +5484,7 @@ See Info node `(elisp)Garbage Collection'.  */)
   if (profiler_memory_running)
     tot_before = total_bytes_of_live_objects ();
 
-  start = current_emacs_time ();
+  start = current_timespec ();
 
   /* In case user calls debug_print during GC,
      don't let that cause a recursive GC.  */
@@ -5263,7 +5517,7 @@ See Info node `(elisp)Garbage Collection'.  */)
              stack_copy = xrealloc (stack_copy, stack_size);
              stack_copy_size = stack_size;
            }
-         memcpy (stack_copy, stack, stack_size);
+         no_sanitize_memcpy (stack_copy, stack, stack_size);
        }
     }
 #endif /* MAX_SAVE_STACK > 0 */
@@ -5304,23 +5558,15 @@ See Info node `(elisp)Garbage Collection'.  */)
        mark_object (tail->var[i]);
   }
   mark_byte_stack ();
+#endif
   {
-    struct catchtag *catch;
     struct handler *handler;
-
-  for (catch = catchlist; catch; catch = catch->next)
-    {
-      mark_object (catch->tag);
-      mark_object (catch->val);
-    }
-  for (handler = handlerlist; handler; handler = handler->next)
-    {
-      mark_object (handler->handler);
-      mark_object (handler->var);
-    }
+    for (handler = handlerlist; handler; handler = handler->next)
+      {
+       mark_object (handler->tag_or_ch);
+       mark_object (handler->val);
+      }
   }
-#endif
-
 #ifdef HAVE_WINDOW_SYSTEM
   mark_fringe_data ();
 #endif
@@ -5329,46 +5575,19 @@ See Info node `(elisp)Garbage Collection'.  */)
   mark_stack ();
 #endif
 
-  /* Everything is now marked, except for the things that require special
-     finalization, i.e. the undo_list.
-     Look thru every buffer's undo list
-     for elements that update markers that were not marked,
-     and delete them.  */
+  /* Everything is now marked, except for the data in font caches
+     and undo lists.  They're compacted by removing an items which
+     aren't reachable otherwise.  */
+
+  compact_font_caches ();
+
   FOR_EACH_BUFFER (nextb)
     {
-      /* If a buffer's undo list is Qt, that means that undo is
-        turned off in that buffer.  Calling truncate_undo_list on
-        Qt tends to return NULL, which effectively turns undo back on.
-        So don't call truncate_undo_list if undo_list is Qt.  */
-      if (! EQ (nextb->INTERNAL_FIELD (undo_list), Qt))
-       {
-         Lisp_Object tail, prev;
-         tail = nextb->INTERNAL_FIELD (undo_list);
-         prev = Qnil;
-         while (CONSP (tail))
-           {
-             if (CONSP (XCAR (tail))
-                 && MARKERP (XCAR (XCAR (tail)))
-                 && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit)
-               {
-                 if (NILP (prev))
-                   nextb->INTERNAL_FIELD (undo_list) = tail = XCDR (tail);
-                 else
-                   {
-                     tail = XCDR (tail);
-                     XSETCDR (prev, tail);
-                   }
-               }
-             else
-               {
-                 prev = tail;
-                 tail = XCDR (tail);
-               }
-           }
-       }
-      /* Now that we have stripped the elements that need not be in the
-        undo_list any more, we can finally mark the list.  */
-      mark_object (nextb->INTERNAL_FIELD (undo_list));
+      if (!EQ (BVAR (nextb, undo_list), Qt))
+       bset_undo_list (nextb, compact_undo_list (BVAR (nextb, undo_list)));
+      /* Now that we have stripped the elements that need not be
+        in the undo_list any more, we can finally mark the list.  */
+      mark_object (BVAR (nextb, undo_list));
     }
 
   gc_sweep ();
@@ -5493,9 +5712,9 @@ See Info node `(elisp)Garbage Collection'.  */)
   /* Accumulate statistics.  */
   if (FLOATP (Vgc_elapsed))
     {
-      EMACS_TIME since_start = sub_emacs_time (current_emacs_time (), start);
+      struct timespec since_start = timespec_sub (current_timespec (), start);
       Vgc_elapsed = make_float (XFLOAT_DATA (Vgc_elapsed)
-                               + EMACS_TIME_TO_DOUBLE (since_start));
+                               + timespectod (since_start));
     }
 
   gcs_done++;
@@ -5540,30 +5759,6 @@ mark_glyph_matrix (struct glyph_matrix *matrix)
       }
 }
 
-
-/* Mark Lisp faces in the face cache C.  */
-
-static void
-mark_face_cache (struct face_cache *c)
-{
-  if (c)
-    {
-      int i, j;
-      for (i = 0; i < c->used; ++i)
-       {
-         struct face *face = FACE_FROM_ID (c->f, i);
-
-         if (face)
-           {
-             for (j = 0; j < LFACE_VECTOR_SIZE; ++j)
-               mark_object (face->lface[j]);
-           }
-       }
-    }
-}
-
-
-\f
 /* Mark reference to a Lisp_Object.
    If the object referred to has not been seen yet, recursively mark
    all the references contained in it.  */
@@ -5663,6 +5858,30 @@ mark_buffer (struct buffer *buffer)
     mark_buffer (buffer->base_buffer);
 }
 
+/* Mark Lisp faces in the face cache C.  */
+
+static void
+mark_face_cache (struct face_cache *c)
+{
+  if (c)
+    {
+      int i, j;
+      for (i = 0; i < c->used; ++i)
+       {
+         struct face *face = FACE_FROM_ID (c->f, i);
+
+         if (face)
+           {
+             if (face->font && !VECTOR_MARKED_P (face->font))
+               mark_vectorlike ((struct Lisp_Vector *) face->font);
+
+             for (j = 0; j < LFACE_VECTOR_SIZE; ++j)
+               mark_object (face->lface[j]);
+           }
+       }
+    }
+}
+
 /* Remove killed buffers or items whose car is a killed buffer from
    LIST, and mark other items.  Return changed LIST, which is marked.  */
 
@@ -5826,8 +6045,21 @@ mark_object (Lisp_Object arg)
            break;
 
          case PVEC_FRAME:
-           mark_vectorlike (ptr);
-           mark_face_cache (((struct frame *) ptr)->face_cache);
+           {
+             struct frame *f = (struct frame *) ptr;
+
+             mark_vectorlike (ptr);
+             mark_face_cache (f->face_cache);
+#ifdef HAVE_WINDOW_SYSTEM
+             if (FRAME_WINDOW_P (f) && FRAME_X_OUTPUT (f))
+               {
+                 struct font *font = FRAME_FONT (f);
+
+                 if (font && !VECTOR_MARKED_P (font))
+                   mark_vectorlike ((struct Lisp_Vector *) font);
+               }
+#endif
+           }
            break;
 
          case PVEC_WINDOW:
@@ -6110,337 +6342,354 @@ survives_gc_p (Lisp_Object obj)
 
 
 \f
-/* Sweep: find all structures not marked, and free them. */
 
+NO_INLINE /* For better stack traces */
 static void
-gc_sweep (void)
+sweep_conses (void)
 {
-  /* Remove or mark entries in weak hash tables.
-     This must be done before any object is unmarked.  */
-  sweep_weak_hash_tables ();
+  register struct cons_block *cblk;
+  struct cons_block **cprev = &cons_block;
+  register int lim = cons_block_index;
+  EMACS_INT num_free = 0, num_used = 0;
 
-  sweep_strings ();
-  check_string_bytes (!noninteractive);
-
-  /* Put all unmarked conses on free list */
-  {
-    register struct cons_block *cblk;
-    struct cons_block **cprev = &cons_block;
-    register int lim = cons_block_index;
-    EMACS_INT num_free = 0, num_used = 0;
-
-    cons_free_list = 0;
-
-    for (cblk = cons_block; cblk; cblk = *cprev)
-      {
-       register int i = 0;
-       int this_free = 0;
-       int ilim = (lim + BITS_PER_INT - 1) / BITS_PER_INT;
+  cons_free_list = 0;
 
-       /* Scan the mark bits an int at a time.  */
-       for (i = 0; i < ilim; i++)
-         {
-           if (cblk->gcmarkbits[i] == -1)
-             {
-               /* Fast path - all cons cells for this int are marked.  */
-               cblk->gcmarkbits[i] = 0;
-               num_used += BITS_PER_INT;
-             }
-           else
-             {
-               /* Some cons cells for this int are not marked.
-                  Find which ones, and free them.  */
-               int start, pos, stop;
-
-               start = i * BITS_PER_INT;
-               stop = lim - start;
-               if (stop > BITS_PER_INT)
-                 stop = BITS_PER_INT;
-               stop += start;
-
-               for (pos = start; pos < stop; pos++)
-                 {
-                   if (!CONS_MARKED_P (&cblk->conses[pos]))
-                     {
-                       this_free++;
-                       cblk->conses[pos].u.chain = cons_free_list;
-                       cons_free_list = &cblk->conses[pos];
+  for (cblk = cons_block; cblk; cblk = *cprev)
+    {
+      register int i = 0;
+      int this_free = 0;
+      int ilim = (lim + BITS_PER_INT - 1) / BITS_PER_INT;
+
+      /* Scan the mark bits an int at a time.  */
+      for (i = 0; i < ilim; i++)
+        {
+          if (cblk->gcmarkbits[i] == -1)
+            {
+              /* Fast path - all cons cells for this int are marked.  */
+              cblk->gcmarkbits[i] = 0;
+              num_used += BITS_PER_INT;
+            }
+          else
+            {
+              /* Some cons cells for this int are not marked.
+                 Find which ones, and free them.  */
+              int start, pos, stop;
+
+              start = i * BITS_PER_INT;
+              stop = lim - start;
+              if (stop > BITS_PER_INT)
+                stop = BITS_PER_INT;
+              stop += start;
+
+              for (pos = start; pos < stop; pos++)
+                {
+                  if (!CONS_MARKED_P (&cblk->conses[pos]))
+                    {
+                      this_free++;
+                      cblk->conses[pos].u.chain = cons_free_list;
+                      cons_free_list = &cblk->conses[pos];
 #if GC_MARK_STACK
-                       cons_free_list->car = Vdead;
+                      cons_free_list->car = Vdead;
 #endif
-                     }
-                   else
-                     {
-                       num_used++;
-                       CONS_UNMARK (&cblk->conses[pos]);
-                     }
-                 }
-             }
-         }
-
-       lim = CONS_BLOCK_SIZE;
-       /* If this block contains only free conses and we have already
-          seen more than two blocks worth of free conses then deallocate
-          this block.  */
-       if (this_free == CONS_BLOCK_SIZE && num_free > CONS_BLOCK_SIZE)
-         {
-           *cprev = cblk->next;
-           /* Unhook from the free list.  */
-           cons_free_list = cblk->conses[0].u.chain;
-           lisp_align_free (cblk);
-         }
-       else
-         {
-           num_free += this_free;
-           cprev = &cblk->next;
-         }
-      }
-    total_conses = num_used;
-    total_free_conses = num_free;
-  }
-
-  /* Put all unmarked floats on free list */
-  {
-    register struct float_block *fblk;
-    struct float_block **fprev = &float_block;
-    register int lim = float_block_index;
-    EMACS_INT num_free = 0, num_used = 0;
-
-    float_free_list = 0;
+                    }
+                  else
+                    {
+                      num_used++;
+                      CONS_UNMARK (&cblk->conses[pos]);
+                    }
+                }
+            }
+        }
 
-    for (fblk = float_block; fblk; fblk = *fprev)
-      {
-       register int i;
-       int this_free = 0;
-       for (i = 0; i < lim; i++)
-         if (!FLOAT_MARKED_P (&fblk->floats[i]))
-           {
-             this_free++;
-             fblk->floats[i].u.chain = float_free_list;
-             float_free_list = &fblk->floats[i];
-           }
-         else
-           {
-             num_used++;
-             FLOAT_UNMARK (&fblk->floats[i]);
-           }
-       lim = FLOAT_BLOCK_SIZE;
-       /* If this block contains only free floats and we have already
-          seen more than two blocks worth of free floats then deallocate
-          this block.  */
-       if (this_free == FLOAT_BLOCK_SIZE && num_free > FLOAT_BLOCK_SIZE)
-         {
-           *fprev = fblk->next;
-           /* Unhook from the free list.  */
-           float_free_list = fblk->floats[0].u.chain;
-           lisp_align_free (fblk);
-         }
-       else
-         {
-           num_free += this_free;
-           fprev = &fblk->next;
-         }
-      }
-    total_floats = num_used;
-    total_free_floats = num_free;
-  }
+      lim = CONS_BLOCK_SIZE;
+      /* If this block contains only free conses and we have already
+         seen more than two blocks worth of free conses then deallocate
+         this block.  */
+      if (this_free == CONS_BLOCK_SIZE && num_free > CONS_BLOCK_SIZE)
+        {
+          *cprev = cblk->next;
+          /* Unhook from the free list.  */
+          cons_free_list = cblk->conses[0].u.chain;
+          lisp_align_free (cblk);
+        }
+      else
+        {
+          num_free += this_free;
+          cprev = &cblk->next;
+        }
+    }
+  total_conses = num_used;
+  total_free_conses = num_free;
+}
 
-  /* Put all unmarked intervals on free list */
-  {
-    register struct interval_block *iblk;
-    struct interval_block **iprev = &interval_block;
-    register int lim = interval_block_index;
-    EMACS_INT num_free = 0, num_used = 0;
+NO_INLINE /* For better stack traces */
+static void
+sweep_floats (void)
+{
+  register struct float_block *fblk;
+  struct float_block **fprev = &float_block;
+  register int lim = float_block_index;
+  EMACS_INT num_free = 0, num_used = 0;
 
-    interval_free_list = 0;
+  float_free_list = 0;
 
-    for (iblk = interval_block; iblk; iblk = *iprev)
-      {
-       register int i;
-       int this_free = 0;
+  for (fblk = float_block; fblk; fblk = *fprev)
+    {
+      register int i;
+      int this_free = 0;
+      for (i = 0; i < lim; i++)
+        if (!FLOAT_MARKED_P (&fblk->floats[i]))
+          {
+            this_free++;
+            fblk->floats[i].u.chain = float_free_list;
+            float_free_list = &fblk->floats[i];
+          }
+        else
+          {
+            num_used++;
+            FLOAT_UNMARK (&fblk->floats[i]);
+          }
+      lim = FLOAT_BLOCK_SIZE;
+      /* If this block contains only free floats and we have already
+         seen more than two blocks worth of free floats then deallocate
+         this block.  */
+      if (this_free == FLOAT_BLOCK_SIZE && num_free > FLOAT_BLOCK_SIZE)
+        {
+          *fprev = fblk->next;
+          /* Unhook from the free list.  */
+          float_free_list = fblk->floats[0].u.chain;
+          lisp_align_free (fblk);
+        }
+      else
+        {
+          num_free += this_free;
+          fprev = &fblk->next;
+        }
+    }
+  total_floats = num_used;
+  total_free_floats = num_free;
+}
 
-       for (i = 0; i < lim; i++)
-         {
-           if (!iblk->intervals[i].gcmarkbit)
-             {
-               set_interval_parent (&iblk->intervals[i], interval_free_list);
-               interval_free_list = &iblk->intervals[i];
-               this_free++;
-             }
-           else
-             {
-               num_used++;
-               iblk->intervals[i].gcmarkbit = 0;
-             }
-         }
-       lim = INTERVAL_BLOCK_SIZE;
-       /* If this block contains only free intervals and we have already
-          seen more than two blocks worth of free intervals then
-          deallocate this block.  */
-       if (this_free == INTERVAL_BLOCK_SIZE && num_free > INTERVAL_BLOCK_SIZE)
-         {
-           *iprev = iblk->next;
-           /* Unhook from the free list.  */
-           interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]);
-           lisp_free (iblk);
-         }
-       else
-         {
-           num_free += this_free;
-           iprev = &iblk->next;
-         }
-      }
-    total_intervals = num_used;
-    total_free_intervals = num_free;
-  }
+NO_INLINE /* For better stack traces */
+static void
+sweep_intervals (void)
+{
+  register struct interval_block *iblk;
+  struct interval_block **iprev = &interval_block;
+  register int lim = interval_block_index;
+  EMACS_INT num_free = 0, num_used = 0;
 
-  /* Put all unmarked symbols on free list */
-  {
-    register struct symbol_block *sblk;
-    struct symbol_block **sprev = &symbol_block;
-    register int lim = symbol_block_index;
-    EMACS_INT num_free = 0, num_used = 0;
+  interval_free_list = 0;
 
-    symbol_free_list = NULL;
+  for (iblk = interval_block; iblk; iblk = *iprev)
+    {
+      register int i;
+      int this_free = 0;
+
+      for (i = 0; i < lim; i++)
+        {
+          if (!iblk->intervals[i].gcmarkbit)
+            {
+              set_interval_parent (&iblk->intervals[i], interval_free_list);
+              interval_free_list = &iblk->intervals[i];
+              this_free++;
+            }
+          else
+            {
+              num_used++;
+              iblk->intervals[i].gcmarkbit = 0;
+            }
+        }
+      lim = INTERVAL_BLOCK_SIZE;
+      /* If this block contains only free intervals and we have already
+         seen more than two blocks worth of free intervals then
+         deallocate this block.  */
+      if (this_free == INTERVAL_BLOCK_SIZE && num_free > INTERVAL_BLOCK_SIZE)
+        {
+          *iprev = iblk->next;
+          /* Unhook from the free list.  */
+          interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]);
+          lisp_free (iblk);
+        }
+      else
+        {
+          num_free += this_free;
+          iprev = &iblk->next;
+        }
+    }
+  total_intervals = num_used;
+  total_free_intervals = num_free;
+}
 
-    for (sblk = symbol_block; sblk; sblk = *sprev)
-      {
-       int this_free = 0;
-       union aligned_Lisp_Symbol *sym = sblk->symbols;
-       union aligned_Lisp_Symbol *end = sym + lim;
+NO_INLINE /* For better stack traces */
+static void
+sweep_symbols (void)
+{
+  register struct symbol_block *sblk;
+  struct symbol_block **sprev = &symbol_block;
+  register int lim = symbol_block_index;
+  EMACS_INT num_free = 0, num_used = 0;
 
-       for (; sym < end; ++sym)
-         {
-           /* Check if the symbol was created during loadup.  In such a case
-              it might be pointed to by pure bytecode which we don't trace,
-              so we conservatively assume that it is live.  */
-           bool pure_p = PURE_POINTER_P (XSTRING (sym->s.name));
+  symbol_free_list = NULL;
 
-           if (!sym->s.gcmarkbit && !pure_p)
-             {
-               if (sym->s.redirect == SYMBOL_LOCALIZED)
-                 xfree (SYMBOL_BLV (&sym->s));
-               sym->s.next = symbol_free_list;
-               symbol_free_list = &sym->s;
+  for (sblk = symbol_block; sblk; sblk = *sprev)
+    {
+      int this_free = 0;
+      union aligned_Lisp_Symbol *sym = sblk->symbols;
+      union aligned_Lisp_Symbol *end = sym + lim;
+
+      for (; sym < end; ++sym)
+        {
+          /* Check if the symbol was created during loadup.  In such a case
+             it might be pointed to by pure bytecode which we don't trace,
+             so we conservatively assume that it is live.  */
+          bool pure_p = PURE_POINTER_P (XSTRING (sym->s.name));
+
+          if (!sym->s.gcmarkbit && !pure_p)
+            {
+              if (sym->s.redirect == SYMBOL_LOCALIZED)
+                xfree (SYMBOL_BLV (&sym->s));
+              sym->s.next = symbol_free_list;
+              symbol_free_list = &sym->s;
 #if GC_MARK_STACK
-               symbol_free_list->function = Vdead;
+              symbol_free_list->function = Vdead;
 #endif
-               ++this_free;
-             }
-           else
-             {
-               ++num_used;
-               if (!pure_p)
-                 UNMARK_STRING (XSTRING (sym->s.name));
-               sym->s.gcmarkbit = 0;
-             }
-         }
+              ++this_free;
+            }
+          else
+            {
+              ++num_used;
+              if (!pure_p)
+                eassert (!STRING_MARKED_P (XSTRING (sym->s.name)));
+              sym->s.gcmarkbit = 0;
+            }
+        }
 
-       lim = SYMBOL_BLOCK_SIZE;
-       /* If this block contains only free symbols and we have already
-          seen more than two blocks worth of free symbols then deallocate
-          this block.  */
-       if (this_free == SYMBOL_BLOCK_SIZE && num_free > SYMBOL_BLOCK_SIZE)
-         {
-           *sprev = sblk->next;
-           /* Unhook from the free list.  */
-           symbol_free_list = sblk->symbols[0].s.next;
-           lisp_free (sblk);
-         }
-       else
-         {
-           num_free += this_free;
-           sprev = &sblk->next;
-         }
-      }
-    total_symbols = num_used;
-    total_free_symbols = num_free;
-  }
+      lim = SYMBOL_BLOCK_SIZE;
+      /* If this block contains only free symbols and we have already
+         seen more than two blocks worth of free symbols then deallocate
+         this block.  */
+      if (this_free == SYMBOL_BLOCK_SIZE && num_free > SYMBOL_BLOCK_SIZE)
+        {
+          *sprev = sblk->next;
+          /* Unhook from the free list.  */
+          symbol_free_list = sblk->symbols[0].s.next;
+          lisp_free (sblk);
+        }
+      else
+        {
+          num_free += this_free;
+          sprev = &sblk->next;
+        }
+    }
+  total_symbols = num_used;
+  total_free_symbols = num_free;
+}
 
-  /* Put all unmarked misc's on free list.
-     For a marker, first unchain it from the buffer it points into.  */
-  {
-    register struct marker_block *mblk;
-    struct marker_block **mprev = &marker_block;
-    register int lim = marker_block_index;
-    EMACS_INT num_free = 0, num_used = 0;
+NO_INLINE /* For better stack traces */
+static void
+sweep_misc (void)
+{
+  register struct marker_block *mblk;
+  struct marker_block **mprev = &marker_block;
+  register int lim = marker_block_index;
+  EMACS_INT num_free = 0, num_used = 0;
 
-    marker_free_list = 0;
+  /* Put all unmarked misc's on free list.  For a marker, first
+     unchain it from the buffer it points into.  */
 
-    for (mblk = marker_block; mblk; mblk = *mprev)
-      {
-       register int i;
-       int this_free = 0;
+  marker_free_list = 0;
 
-       for (i = 0; i < lim; i++)
-         {
-           if (!mblk->markers[i].m.u_any.gcmarkbit)
-             {
-               if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker)
-                 unchain_marker (&mblk->markers[i].m.u_marker);
-               /* Set the type of the freed object to Lisp_Misc_Free.
-                  We could leave the type alone, since nobody checks it,
-                  but this might catch bugs faster.  */
-               mblk->markers[i].m.u_marker.type = Lisp_Misc_Free;
-               mblk->markers[i].m.u_free.chain = marker_free_list;
-               marker_free_list = &mblk->markers[i].m;
-               this_free++;
-             }
-           else
-             {
-               num_used++;
-               mblk->markers[i].m.u_any.gcmarkbit = 0;
-             }
-         }
-       lim = MARKER_BLOCK_SIZE;
-       /* If this block contains only free markers and we have already
-          seen more than two blocks worth of free markers then deallocate
-          this block.  */
-       if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE)
-         {
-           *mprev = mblk->next;
-           /* Unhook from the free list.  */
-           marker_free_list = mblk->markers[0].m.u_free.chain;
-           lisp_free (mblk);
-         }
-       else
-         {
-           num_free += this_free;
-           mprev = &mblk->next;
-         }
-      }
+  for (mblk = marker_block; mblk; mblk = *mprev)
+    {
+      register int i;
+      int this_free = 0;
+
+      for (i = 0; i < lim; i++)
+        {
+          if (!mblk->markers[i].m.u_any.gcmarkbit)
+            {
+              if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker)
+                unchain_marker (&mblk->markers[i].m.u_marker);
+              /* Set the type of the freed object to Lisp_Misc_Free.
+                 We could leave the type alone, since nobody checks it,
+                 but this might catch bugs faster.  */
+              mblk->markers[i].m.u_marker.type = Lisp_Misc_Free;
+              mblk->markers[i].m.u_free.chain = marker_free_list;
+              marker_free_list = &mblk->markers[i].m;
+              this_free++;
+            }
+          else
+            {
+              num_used++;
+              mblk->markers[i].m.u_any.gcmarkbit = 0;
+            }
+        }
+      lim = MARKER_BLOCK_SIZE;
+      /* If this block contains only free markers and we have already
+         seen more than two blocks worth of free markers then deallocate
+         this block.  */
+      if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE)
+        {
+          *mprev = mblk->next;
+          /* Unhook from the free list.  */
+          marker_free_list = mblk->markers[0].m.u_free.chain;
+          lisp_free (mblk);
+        }
+      else
+        {
+          num_free += this_free;
+          mprev = &mblk->next;
+        }
+    }
 
-    total_markers = num_used;
-    total_free_markers = num_free;
-  }
+  total_markers = num_used;
+  total_free_markers = num_free;
+}
 
-  /* Free all unmarked buffers */
-  {
-    register struct buffer *buffer, **bprev = &all_buffers;
+NO_INLINE /* For better stack traces */
+static void
+sweep_buffers (void)
+{
+  register struct buffer *buffer, **bprev = &all_buffers;
 
-    total_buffers = 0;
-    for (buffer = all_buffers; buffer; buffer = *bprev)
-      if (!VECTOR_MARKED_P (buffer))
-       {
-         *bprev = buffer->next;
-         lisp_free (buffer);
-       }
-      else
-       {
-         VECTOR_UNMARK (buffer);
-         /* Do not use buffer_(set|get)_intervals here.  */
-         buffer->text->intervals = balance_intervals (buffer->text->intervals);
-         total_buffers++;
-         bprev = &buffer->next;
-       }
-  }
+  total_buffers = 0;
+  for (buffer = all_buffers; buffer; buffer = *bprev)
+    if (!VECTOR_MARKED_P (buffer))
+      {
+        *bprev = buffer->next;
+        lisp_free (buffer);
+      }
+    else
+      {
+        VECTOR_UNMARK (buffer);
+        /* Do not use buffer_(set|get)_intervals here.  */
+        buffer->text->intervals = balance_intervals (buffer->text->intervals);
+        total_buffers++;
+        bprev = &buffer->next;
+      }
+}
 
+/* Sweep: find all structures not marked, and free them.  */
+static void
+gc_sweep (void)
+{
+  /* Remove or mark entries in weak hash tables.
+     This must be done before any object is unmarked.  */
+  sweep_weak_hash_tables ();
+
+  sweep_strings ();
+  check_string_bytes (!noninteractive);
+  sweep_conses ();
+  sweep_floats ();
+  sweep_intervals ();
+  sweep_symbols ();
+  sweep_misc ();
+  sweep_buffers ();
   sweep_vectors ();
   check_string_bytes (!noninteractive);
 }
 
-
-
 \f
 /* Debugging aids.  */
 
@@ -6452,7 +6701,12 @@ We divide the value by 1024 to make sure it fits in a Lisp integer.  */)
 {
   Lisp_Object end;
 
+#ifdef HAVE_NS
+  /* Avoid warning.  sbrk has no relation to memory allocated anyway.  */
+  XSETINT (end, 0);
+#else
   XSETINT (end, (intptr_t) (char *) sbrk (0) / 1024);
+#endif
 
   return end;
 }
@@ -6584,6 +6838,10 @@ init_alloc (void)
 #endif
   Vgc_elapsed = make_float (0.0);
   gcs_done = 0;
+
+#if USE_VALGRIND
+  valgrind_p = RUNNING_ON_VALGRIND != 0;
+#endif
 }
 
 void