Merge from trunk.
[bpt/emacs.git] / src / alloc.c
index 0bfc4c1..f325b6e 100644 (file)
@@ -70,7 +70,7 @@ extern POINTER_TYPE *sbrk ();
 #include <malloc.h>
 /* malloc.h #defines this as size_t, at least in glibc2.  */
 #ifndef __malloc_size_t
-#define __malloc_size_t int
+#define __malloc_size_t size_t
 #endif
 
 /* Specify maximum number of areas to mmap.  It would be nice to use a
@@ -214,12 +214,12 @@ EMACS_INT pure[(PURESIZE + sizeof (EMACS_INT) - 1) / sizeof (EMACS_INT)] = {1,};
 /* Pointer to the pure area, and its size.  */
 
 static char *purebeg;
-static size_t pure_size;
+static ptrdiff_t pure_size;
 
 /* Number of bytes of pure storage used before pure storage overflowed.
    If this is non-zero, this implies that an overflow occurred.  */
 
-static size_t pure_bytes_used_before_overflow;
+static ptrdiff_t pure_bytes_used_before_overflow;
 
 /* Value is non-zero if P points into pure space.  */
 
@@ -252,7 +252,7 @@ const char *pending_malloc_warning;
 
 #if MAX_SAVE_STACK > 0
 static char *stack_copy;
-static size_t stack_copy_size;
+static ptrdiff_t stack_copy_size;
 #endif
 
 /* Non-zero means ignore malloc warnings.  Set during initialization.
@@ -486,14 +486,15 @@ buffer_memory_full (EMACS_INT nbytes)
 
 
 #ifndef XMALLOC_OVERRUN_CHECK
-#define XMALLOC_OVERRUN_CHECK_SIZE 0
+#define XMALLOC_OVERRUN_CHECK_OVERHEAD 0
 #else
 
-/* Check for overrun in malloc'ed buffers by wrapping a 16 byte header
-   and a 16 byte trailer around each block.
+/* Check for overrun in malloc'ed buffers by wrapping a header and trailer
+   around each block.
 
-   The header consists of 12 fixed bytes + a 4 byte integer contaning the
-   original block size, while the trailer consists of 16 fixed bytes.
+   The header consists of 16 fixed bytes followed by sizeof (size_t) bytes
+   containing the original block size in little-endian order,
+   while the trailer consists of 16 fixed bytes.
 
    The header is used to detect whether this block has been allocated
    through these functions -- as it seems that some low-level libc
@@ -502,31 +503,47 @@ buffer_memory_full (EMACS_INT nbytes)
 
 
 #define XMALLOC_OVERRUN_CHECK_SIZE 16
+#define XMALLOC_OVERRUN_CHECK_OVERHEAD \
+  (2 * XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t))
 
-static char xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE-4] =
-  { 0x9a, 0x9b, 0xae, 0xaf,
-    0xbf, 0xbe, 0xce, 0xcf,
-    0xea, 0xeb, 0xec, 0xed };
+static char const xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE] =
+  { '\x9a', '\x9b', '\xae', '\xaf',
+    '\xbf', '\xbe', '\xce', '\xcf',
+    '\xea', '\xeb', '\xec', '\xed',
+    '\xdf', '\xde', '\x9c', '\x9d' };
 
-static char xmalloc_overrun_check_trailer[XMALLOC_OVERRUN_CHECK_SIZE] =
-  { 0xaa, 0xab, 0xac, 0xad,
-    0xba, 0xbb, 0xbc, 0xbd,
-    0xca, 0xcb, 0xcc, 0xcd,
-    0xda, 0xdb, 0xdc, 0xdd };
+static char const xmalloc_overrun_check_trailer[XMALLOC_OVERRUN_CHECK_SIZE] =
+  { '\xaa', '\xab', '\xac', '\xad',
+    '\xba', '\xbb', '\xbc', '\xbd',
+    '\xca', '\xcb', '\xcc', '\xcd',
+    '\xda', '\xdb', '\xdc', '\xdd' };
 
-/* Macros to insert and extract the block size in the header.  */
+/* Insert and extract the block size in the header.  */
 
-#define XMALLOC_PUT_SIZE(ptr, size)    \
-  (ptr[-1] = (size & 0xff),            \
-   ptr[-2] = ((size >> 8) & 0xff),     \
-   ptr[-3] = ((size >> 16) & 0xff),    \
-   ptr[-4] = ((size >> 24) & 0xff))
+static void
+xmalloc_put_size (unsigned char *ptr, size_t size)
+{
+  int i;
+  for (i = 0; i < sizeof (size_t); i++)
+    {
+      *--ptr = size & (1 << CHAR_BIT) - 1;
+      size >>= CHAR_BIT;
+    }
+}
 
-#define XMALLOC_GET_SIZE(ptr)                  \
-  (size_t)((unsigned)(ptr[-1])         |       \
-          ((unsigned)(ptr[-2]) << 8)   |       \
-          ((unsigned)(ptr[-3]) << 16)  |       \
-          ((unsigned)(ptr[-4]) << 24))
+static size_t
+xmalloc_get_size (unsigned char *ptr)
+{
+  size_t size = 0;
+  int i;
+  ptr -= sizeof (size_t);
+  for (i = 0; i < sizeof (size_t); i++)
+    {
+      size <<= CHAR_BIT;
+      size += *ptr++;
+    }
+  return size;
+}
 
 
 /* The call depth in overrun_check functions.  For example, this might happen:
@@ -545,10 +562,10 @@ static char xmalloc_overrun_check_trailer[XMALLOC_OVERRUN_CHECK_SIZE] =
 
    xfree(10032)
      overrun_check_free(10032)
-       decrease overhed
+       decrease overhead
        free(10016)  <-  crash, because 10000 is the original pointer.  */
 
-static int check_depth;
+static ptrdiff_t check_depth;
 
 /* Like malloc, but wraps allocated block with header and trailer.  */
 
@@ -556,15 +573,16 @@ static POINTER_TYPE *
 overrun_check_malloc (size_t size)
 {
   register unsigned char *val;
-  size_t overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_SIZE*2 : 0;
+  int overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_OVERHEAD : 0;
+  if (SIZE_MAX - overhead < size)
+    abort ();
 
   val = (unsigned char *) malloc (size + overhead);
   if (val && check_depth == 1)
     {
-      memcpy (val, xmalloc_overrun_check_header,
-             XMALLOC_OVERRUN_CHECK_SIZE - 4);
-      val += XMALLOC_OVERRUN_CHECK_SIZE;
-      XMALLOC_PUT_SIZE(val, size);
+      memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE);
+      val += XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t);
+      xmalloc_put_size (val, size);
       memcpy (val + size, xmalloc_overrun_check_trailer,
              XMALLOC_OVERRUN_CHECK_SIZE);
     }
@@ -580,31 +598,32 @@ static POINTER_TYPE *
 overrun_check_realloc (POINTER_TYPE *block, size_t size)
 {
   register unsigned char *val = (unsigned char *) block;
-  size_t overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_SIZE*2 : 0;
+  int overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_OVERHEAD : 0;
+  if (SIZE_MAX - overhead < size)
+    abort ();
 
   if (val
       && check_depth == 1
       && memcmp (xmalloc_overrun_check_header,
-                val - XMALLOC_OVERRUN_CHECK_SIZE,
-                XMALLOC_OVERRUN_CHECK_SIZE - 4) == 0)
+                val - XMALLOC_OVERRUN_CHECK_SIZE - sizeof (size_t),
+                XMALLOC_OVERRUN_CHECK_SIZE) == 0)
     {
-      size_t osize = XMALLOC_GET_SIZE (val);
+      size_t osize = xmalloc_get_size (val);
       if (memcmp (xmalloc_overrun_check_trailer, val + osize,
                  XMALLOC_OVERRUN_CHECK_SIZE))
        abort ();
       memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE);
-      val -= XMALLOC_OVERRUN_CHECK_SIZE;
-      memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE);
+      val -= XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t);
+      memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t));
     }
 
   val = (unsigned char *) realloc ((POINTER_TYPE *)val, size + overhead);
 
   if (val && check_depth == 1)
     {
-      memcpy (val, xmalloc_overrun_check_header,
-             XMALLOC_OVERRUN_CHECK_SIZE - 4);
-      val += XMALLOC_OVERRUN_CHECK_SIZE;
-      XMALLOC_PUT_SIZE(val, size);
+      memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE);
+      val += XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t);
+      xmalloc_put_size (val, size);
       memcpy (val + size, xmalloc_overrun_check_trailer,
              XMALLOC_OVERRUN_CHECK_SIZE);
     }
@@ -623,20 +642,20 @@ overrun_check_free (POINTER_TYPE *block)
   if (val
       && check_depth == 1
       && memcmp (xmalloc_overrun_check_header,
-                val - XMALLOC_OVERRUN_CHECK_SIZE,
-                XMALLOC_OVERRUN_CHECK_SIZE - 4) == 0)
+                val - XMALLOC_OVERRUN_CHECK_SIZE - sizeof (size_t),
+                XMALLOC_OVERRUN_CHECK_SIZE) == 0)
     {
-      size_t osize = XMALLOC_GET_SIZE (val);
+      size_t osize = xmalloc_get_size (val);
       if (memcmp (xmalloc_overrun_check_trailer, val + osize,
                  XMALLOC_OVERRUN_CHECK_SIZE))
        abort ();
 #ifdef XMALLOC_CLEAR_FREE_MEMORY
-      val -= XMALLOC_OVERRUN_CHECK_SIZE;
-      memset (val, 0xff, osize + XMALLOC_OVERRUN_CHECK_SIZE*2);
+      val -= XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t);
+      memset (val, 0xff, osize + XMALLOC_OVERRUN_CHECK_OVERHEAD);
 #else
       memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE);
-      val -= XMALLOC_OVERRUN_CHECK_SIZE;
-      memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE);
+      val -= XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t);
+      memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t));
 #endif
     }
 
@@ -1258,7 +1277,7 @@ emacs_blocked_realloc (void *ptr, size_t size, const void *ptr2)
    calls malloc because it is the first call, and we have an endless loop.  */
 
 void
-reset_malloc_hooks ()
+reset_malloc_hooks (void)
 {
   __free_hook = old_free_hook;
   __malloc_hook = old_malloc_hook;
@@ -1344,10 +1363,6 @@ static EMACS_INT total_free_intervals, total_intervals;
 
 static INTERVAL interval_free_list;
 
-/* Total number of interval blocks now in use.  */
-
-static int n_interval_blocks;
-
 
 /* Initialize interval allocation.  */
 
@@ -1357,7 +1372,6 @@ init_intervals (void)
   interval_block = NULL;
   interval_block_index = INTERVAL_BLOCK_SIZE;
   interval_free_list = 0;
-  n_interval_blocks = 0;
 }
 
 
@@ -1389,7 +1403,6 @@ make_interval (void)
          newi->next = interval_block;
          interval_block = newi;
          interval_block_index = 0;
-         n_interval_blocks++;
        }
       val = &interval_block->intervals[interval_block_index++];
     }
@@ -1582,10 +1595,9 @@ static struct sblock *oldest_sblock, *current_sblock;
 
 static struct sblock *large_sblocks;
 
-/* List of string_block structures, and how many there are.  */
+/* List of string_block structures.  */
 
 static struct string_block *string_blocks;
-static int n_string_blocks;
 
 /* Free-list of Lisp_Strings.  */
 
@@ -1668,7 +1680,8 @@ static char const string_overrun_cookie[GC_STRING_OVERRUN_COOKIE_SIZE] =
    calculating a value to be passed to malloc.  */
 #define STRING_BYTES_MAX                                         \
   min (STRING_BYTES_BOUND,                                       \
-       ((SIZE_MAX - XMALLOC_OVERRUN_CHECK_SIZE - GC_STRING_EXTRA  \
+       ((SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD               \
+        - GC_STRING_EXTRA                                        \
         - offsetof (struct sblock, first_data)                   \
         - SDATA_DATA_OFFSET)                                     \
        & ~(sizeof (EMACS_INT) - 1)))
@@ -1681,7 +1694,6 @@ init_strings (void)
   total_strings = total_free_strings = total_string_size = 0;
   oldest_sblock = current_sblock = large_sblocks = NULL;
   string_blocks = NULL;
-  n_string_blocks = 0;
   string_free_list = NULL;
   empty_unibyte_string = make_pure_string ("", 0, 0, 0);
   empty_multibyte_string = make_pure_string ("", 0, 0, 1);
@@ -1813,7 +1825,6 @@ allocate_string (void)
       memset (b, 0, sizeof *b);
       b->next = string_blocks;
       string_blocks = b;
-      ++n_string_blocks;
 
       for (i = STRING_BLOCK_SIZE - 1; i >= 0; --i)
        {
@@ -2042,7 +2053,6 @@ sweep_strings (void)
          && total_free_strings > STRING_BLOCK_SIZE)
        {
          lisp_free (b);
-         --n_string_blocks;
          string_free_list = free_list_before;
        }
       else
@@ -2267,12 +2277,14 @@ LENGTH must be a number.  INIT matters only in whether it is t or nil.  */)
   p = XBOOL_VECTOR (val);
   p->size = XFASTINT (length);
 
-  memset (p->data, NILP (init) ? 0 : -1, length_in_chars);
+  if (length_in_chars)
+    {
+      memset (p->data, ! NILP (init) ? -1 : 0, length_in_chars);
 
-  /* Clear the extraneous bits in the last byte.  */
-  if (XINT (length) != length_in_chars * BOOL_VECTOR_BITS_PER_CHAR)
-    p->data[length_in_chars - 1]
-      &= (1 << (XINT (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1;
+      /* Clear any extraneous bits in the last byte.  */
+      p->data[length_in_chars - 1]
+       &= (1 << (XINT (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1;
+    }
 
   return val;
 }
@@ -2477,10 +2489,6 @@ static struct float_block *float_block;
 
 static int float_block_index;
 
-/* Total number of float blocks now in use.  */
-
-static int n_float_blocks;
-
 /* Free-list of Lisp_Floats.  */
 
 static struct Lisp_Float *float_free_list;
@@ -2494,7 +2502,6 @@ init_float (void)
   float_block = NULL;
   float_block_index = FLOAT_BLOCK_SIZE; /* Force alloc of new float_block.   */
   float_free_list = 0;
-  n_float_blocks = 0;
 }
 
 
@@ -2528,7 +2535,6 @@ make_float (double float_value)
          memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
          float_block = new;
          float_block_index = 0;
-         n_float_blocks++;
        }
       XSETFLOAT (val, &float_block->floats[float_block_index]);
       float_block_index++;
@@ -2593,10 +2599,6 @@ static int cons_block_index;
 
 static struct Lisp_Cons *cons_free_list;
 
-/* Total number of cons blocks now in use.  */
-
-static int n_cons_blocks;
-
 
 /* Initialize cons allocation.  */
 
@@ -2606,7 +2608,6 @@ init_cons (void)
   cons_block = NULL;
   cons_block_index = CONS_BLOCK_SIZE; /* Force alloc of new cons_block.  */
   cons_free_list = 0;
-  n_cons_blocks = 0;
 }
 
 
@@ -2650,7 +2651,6 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
          new->next = cons_block;
          cons_block = new;
          cons_block_index = 0;
-         n_cons_blocks++;
        }
       XSETCONS (val, &cons_block->conses[cons_block_index]);
       cons_block_index++;
@@ -2719,7 +2719,7 @@ DEFUN ("list", Flist, Slist, 0, MANY, 0,
        doc: /* Return a newly created list with specified arguments as elements.
 Any number of arguments, even zero arguments, are allowed.
 usage: (list &rest OBJECTS)  */)
-  (size_t nargs, register Lisp_Object *args)
+  (ptrdiff_t nargs, Lisp_Object *args)
 {
   register Lisp_Object val;
   val = Qnil;
@@ -2789,10 +2789,12 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0,
 
 static struct Lisp_Vector *all_vectors;
 
-/* Total number of vector-like objects now in use.  */
-
-static int n_vectors;
-
+/* Handy constants for vectorlike objects.  */
+enum
+  {
+    header_size = offsetof (struct Lisp_Vector, contents),
+    word_size = sizeof (Lisp_Object)
+  };
 
 /* Value is a pointer to a newly allocated Lisp_Vector structure
    with room for LEN Lisp_Objects.  */
@@ -2802,12 +2804,6 @@ allocate_vectorlike (EMACS_INT len)
 {
   struct Lisp_Vector *p;
   size_t nbytes;
-  ptrdiff_t nbytes_max = min (PTRDIFF_MAX, SIZE_MAX);
-  int header_size = offsetof (struct Lisp_Vector, contents);
-  int word_size = sizeof p->contents[0];
-
-  if ((nbytes_max - header_size) / word_size < len)
-    memory_full (SIZE_MAX);
 
   MALLOC_BLOCK_INPUT;
 
@@ -2837,18 +2833,22 @@ allocate_vectorlike (EMACS_INT len)
 
   MALLOC_UNBLOCK_INPUT;
 
-  ++n_vectors;
   return p;
 }
 
 
-/* Allocate a vector with NSLOTS slots.  */
+/* Allocate a vector with LEN slots.  */
 
 struct Lisp_Vector *
-allocate_vector (EMACS_INT nslots)
+allocate_vector (EMACS_INT len)
 {
-  struct Lisp_Vector *v = allocate_vectorlike (nslots);
-  v->header.size = nslots;
+  struct Lisp_Vector *v;
+  ptrdiff_t nbytes_max = min (PTRDIFF_MAX, SIZE_MAX);
+
+  if (min ((nbytes_max - header_size) / word_size, MOST_POSITIVE_FIXNUM) < len)
+    memory_full (SIZE_MAX);
+  v = allocate_vectorlike (len);
+  v->header.size = len;
   return v;
 }
 
@@ -2859,7 +2859,7 @@ struct Lisp_Vector *
 allocate_pseudovector (int memlen, int lisplen, EMACS_INT tag)
 {
   struct Lisp_Vector *v = allocate_vectorlike (memlen);
-  EMACS_INT i;
+  int i;
 
   /* Only the first lisplen slots will be traced normally by the GC.  */
   for (i = 0; i < lisplen; ++i)
@@ -2940,10 +2940,10 @@ DEFUN ("vector", Fvector, Svector, 0, MANY, 0,
        doc: /* Return a newly created vector with specified arguments as elements.
 Any number of arguments, even zero arguments, are allowed.
 usage: (vector &rest OBJECTS)  */)
-  (register size_t nargs, Lisp_Object *args)
+  (ptrdiff_t nargs, Lisp_Object *args)
 {
   register Lisp_Object len, val;
-  register size_t i;
+  ptrdiff_t i;
   register struct Lisp_Vector *p;
 
   XSETFASTINT (len, nargs);
@@ -2971,15 +2971,15 @@ argument to catch the left-over arguments.  If such an integer is used, the
 arguments will not be dynamically bound but will be instead pushed on the
 stack before executing the byte-code.
 usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INTERACTIVE-SPEC &rest ELEMENTS)  */)
-  (register size_t nargs, Lisp_Object *args)
+  (ptrdiff_t nargs, Lisp_Object *args)
 {
   register Lisp_Object len, val;
-  register size_t i;
+  ptrdiff_t i;
   register struct Lisp_Vector *p;
 
   XSETFASTINT (len, nargs);
   if (!NILP (Vpurify_flag))
-    val = make_pure_vector ((EMACS_INT) nargs);
+    val = make_pure_vector (nargs);
   else
     val = Fmake_vector (len, Qnil);
 
@@ -3033,10 +3033,6 @@ static int symbol_block_index;
 
 static struct Lisp_Symbol *symbol_free_list;
 
-/* Total number of symbol blocks now in use.  */
-
-static int n_symbol_blocks;
-
 
 /* Initialize symbol allocation.  */
 
@@ -3046,7 +3042,6 @@ init_symbol (void)
   symbol_block = NULL;
   symbol_block_index = SYMBOL_BLOCK_SIZE;
   symbol_free_list = 0;
-  n_symbol_blocks = 0;
 }
 
 
@@ -3079,7 +3074,6 @@ Its value and function definition are void, and its property list is nil.  */)
          new->next = symbol_block;
          symbol_block = new;
          symbol_block_index = 0;
-         n_symbol_blocks++;
        }
       XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]);
       symbol_block_index++;
@@ -3127,17 +3121,12 @@ static int marker_block_index;
 
 static union Lisp_Misc *marker_free_list;
 
-/* Total number of marker blocks now in use.  */
-
-static int n_marker_blocks;
-
 static void
 init_marker (void)
 {
   marker_block = NULL;
   marker_block_index = MARKER_BLOCK_SIZE;
   marker_free_list = 0;
-  n_marker_blocks = 0;
 }
 
 /* Return a newly allocated Lisp_Misc object, with no substructure.  */
@@ -3166,7 +3155,6 @@ allocate_misc (void)
          new->next = marker_block;
          marker_block = new;
          marker_block_index = 0;
-         n_marker_blocks++;
          total_free_markers += MARKER_BLOCK_SIZE;
        }
       XSETMISC (val, &marker_block->markers[marker_block_index]);
@@ -3199,7 +3187,7 @@ free_misc (Lisp_Object misc)
    The unwind function can get the C values back using XSAVE_VALUE.  */
 
 Lisp_Object
-make_save_value (void *pointer, int integer)
+make_save_value (void *pointer, ptrdiff_t integer)
 {
   register Lisp_Object val;
   register struct Lisp_Save_Value *p;
@@ -3352,7 +3340,7 @@ refill_memory_reserve (void)
 {
 #ifndef SYSTEM_MALLOC
   if (spare_memory[0] == 0)
-    spare_memory[0] = (char *) malloc ((size_t) SPARE_MEMORY);
+    spare_memory[0] = (char *) malloc (SPARE_MEMORY);
   if (spare_memory[1] == 0)
     spare_memory[1] = (char *) lisp_align_malloc (sizeof (struct cons_block),
                                                  MEM_TYPE_CONS);
@@ -3944,11 +3932,11 @@ static Lisp_Object zombies[MAX_ZOMBIES];
 
 /* Number of zombie objects.  */
 
-static int nzombies;
+static EMACS_INT nzombies;
 
 /* Number of garbage collections.  */
 
-static int ngcs;
+static EMACS_INT ngcs;
 
 /* Average percentage of zombies per collection.  */
 
@@ -3956,7 +3944,7 @@ static double avg_zombies;
 
 /* Max. number of live and zombie objects.  */
 
-static int max_live, max_zombies;
+static EMACS_INT max_live, max_zombies;
 
 /* Average number of live objects per GC.  */
 
@@ -3967,7 +3955,7 @@ DEFUN ("gc-status", Fgc_status, Sgc_status, 0, 0, "",
   (void)
 {
   Lisp_Object args[8], zombie_list = Qnil;
-  int i;
+  EMACS_INT i;
   for (i = 0; i < nzombies; i++)
     zombie_list = Fcons (zombies[i], zombie_list);
   args[0] = build_string ("%d GCs, avg live/zombies = %.2f/%.2f (%f%%), max %d/%d\nzombies: %S");
@@ -4277,7 +4265,7 @@ static void
 check_gcpros (void)
 {
   struct gcpro *p;
-  size_t i;
+  ptrdiff_t i;
 
   for (p = gcprolist; p; p = p->next)
     for (i = 0; i < p->nvars; ++i)
@@ -4294,7 +4282,7 @@ dump_zombies (void)
 {
   int i;
 
-  fprintf (stderr, "\nZombies kept alive = %d:\n", nzombies);
+  fprintf (stderr, "\nZombies kept alive = %"pI":\n", nzombies);
   for (i = 0; i < min (MAX_ZOMBIES, nzombies); ++i)
     {
       fprintf (stderr, "  %d = ", i);
@@ -4866,9 +4854,8 @@ int
 inhibit_garbage_collection (void)
 {
   int count = SPECPDL_INDEX ();
-  int nbits = min (VALBITS, BITS_PER_INT);
 
-  specbind (Qgc_cons_threshold, make_number (((EMACS_INT) 1 << (nbits - 1)) - 1));
+  specbind (Qgc_cons_threshold, make_number (MOST_POSITIVE_FIXNUM));
   return count;
 }
 
@@ -4888,7 +4875,7 @@ returns nil, because real GC can't be done.  */)
 {
   register struct specbinding *bind;
   char stack_top_variable;
-  register size_t i;
+  ptrdiff_t i;
   int message_p;
   Lisp_Object total[8];
   int count = SPECPDL_INDEX ();
@@ -4955,7 +4942,7 @@ returns nil, because real GC can't be done.  */)
   if (NILP (Vpurify_flag))
     {
       char *stack;
-      size_t stack_size;
+      ptrdiff_t stack_size;
       if (&stack_top_variable < stack_bottom)
        {
          stack = &stack_top_variable;
@@ -5266,7 +5253,7 @@ static int last_marked_index;
    links of a list, in mark_object.  In debugging,
    the call to abort will hit a breakpoint.
    Normally this is zero and the check never goes off.  */
-static size_t mark_object_loop_halt;
+ptrdiff_t mark_object_loop_halt EXTERNALLY_VISIBLE;
 
 static void
 mark_vectorlike (struct Lisp_Vector *ptr)
@@ -5323,7 +5310,7 @@ mark_object (Lisp_Object arg)
   void *po;
   struct mem_node *m;
 #endif
-  size_t cdr_count = 0;
+  ptrdiff_t cdr_count = 0;
 
  loop:
 
@@ -5554,7 +5541,7 @@ mark_object (Lisp_Object arg)
            if (ptr->dogc)
              {
                Lisp_Object *p = (Lisp_Object *) ptr->pointer;
-               int nelt;
+               ptrdiff_t nelt;
                for (nelt = ptr->integer; nelt > 0; nelt--, p++)
                  mark_maybe_object (*p);
              }
@@ -5652,7 +5639,8 @@ mark_buffer (Lisp_Object buf)
   /* buffer-local Lisp variables start at `undo_list',
      tho only the ones from `name' on are GC'd normally.  */
   for (ptr = &buffer->BUFFER_INTERNAL_FIELD (name);
-       (char *)ptr < (char *)buffer + sizeof (struct buffer);
+       ptr <= &PER_BUFFER_VALUE (buffer,
+                                PER_BUFFER_VAR_OFFSET (LAST_FIELD_PER_BUFFER));
        ptr++)
     mark_object (*ptr);
 
@@ -5815,7 +5803,6 @@ gc_sweep (void)
            /* Unhook from the free list.  */
            cons_free_list = cblk->conses[0].u.chain;
            lisp_align_free (cblk);
-           n_cons_blocks--;
          }
        else
          {
@@ -5862,7 +5849,6 @@ gc_sweep (void)
            /* Unhook from the free list.  */
            float_free_list = fblk->floats[0].u.chain;
            lisp_align_free (fblk);
-           n_float_blocks--;
          }
        else
          {
@@ -5912,7 +5898,6 @@ gc_sweep (void)
            /* Unhook from the free list.  */
            interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]);
            lisp_free (iblk);
-           n_interval_blocks--;
          }
        else
          {
@@ -5976,7 +5961,6 @@ gc_sweep (void)
            /* Unhook from the free list.  */
            symbol_free_list = sblk->symbols[0].next;
            lisp_free (sblk);
-           n_symbol_blocks--;
          }
        else
          {
@@ -6033,7 +6017,6 @@ gc_sweep (void)
            /* Unhook from the free list.  */
            marker_free_list = mblk->markers[0].u_free.chain;
            lisp_free (mblk);
-           n_marker_blocks--;
          }
        else
          {
@@ -6083,7 +6066,6 @@ gc_sweep (void)
            all_vectors = vector->header.next.vector;
          next = vector->header.next.vector;
          lisp_free (vector);
-         n_vectors--;
          vector = next;
 
        }
@@ -6290,8 +6272,7 @@ do hash-consing of the objects allocated to pure space.  */);
   DEFVAR_LISP ("post-gc-hook", Vpost_gc_hook,
               doc: /* Hook run after garbage collection has finished.  */);
   Vpost_gc_hook = Qnil;
-  Qpost_gc_hook = intern_c_string ("post-gc-hook");
-  staticpro (&Qpost_gc_hook);
+  DEFSYM (Qpost_gc_hook, "post-gc-hook");
 
   DEFVAR_LISP ("memory-signal-data", Vmemory_signal_data,
               doc: /* Precomputed `signal' argument for memory-full error.  */);
@@ -6305,11 +6286,8 @@ do hash-consing of the objects allocated to pure space.  */);
               doc: /* Non-nil means Emacs cannot get much more Lisp memory.  */);
   Vmemory_full = Qnil;
 
-  staticpro (&Qgc_cons_threshold);
-  Qgc_cons_threshold = intern_c_string ("gc-cons-threshold");
-
-  staticpro (&Qchar_table_extra_slots);
-  Qchar_table_extra_slots = intern_c_string ("char-table-extra-slots");
+  DEFSYM (Qgc_cons_threshold, "gc-cons-threshold");
+  DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots");
 
   DEFVAR_LISP ("gc-elapsed", Vgc_elapsed,
               doc: /* Accumulated time elapsed in garbage collections.