]> code.delx.au - gnu-emacs/blobdiff - src/alloc.c
Add 2009 to copyright years.
[gnu-emacs] / src / alloc.c
index f847b4052b7d9a3e69acf4aa6816d5372bef1372..90c743a5d38f14aabdbaae476c06bfb808db7021 100644 (file)
@@ -1,13 +1,14 @@
 /* Storage allocation and gc for GNU Emacs Lisp interpreter.
    Copyright (C) 1985, 1986, 1988, 1993, 1994, 1995, 1997, 1998, 1999,
-      2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007  Free Software Foundation, Inc.
+      2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+      Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <stdio.h>
@@ -55,6 +54,7 @@ Boston, MA 02110-1301, USA.  */
 #include "blockinput.h"
 #include "character.h"
 #include "syssignal.h"
+#include "termhooks.h"         /* For struct terminal.  */
 #include <setjmp.h>
 
 /* GC_MALLOC_CHECK defined means perform validity checks of malloc'd
@@ -240,7 +240,7 @@ static int total_free_floats, total_floats;
    out of memory.  We keep one large block, four cons-blocks, and
    two string blocks.  */
 
-char *spare_memory[7];
+static char *spare_memory[7];
 
 /* Amount of spare memory to keep in large reserve block.  */
 
@@ -266,7 +266,7 @@ Lisp_Object Vmemory_full;
    remapping on more recent systems because this is less important
    nowadays than in the days of small memories and timesharing.  */
 
-EMACS_INT pure[PURESIZE / sizeof (EMACS_INT)] = {1,};
+EMACS_INT pure[(PURESIZE + sizeof (EMACS_INT) - 1) / sizeof (EMACS_INT)] = {1,};
 #define PUREBEG (char *) pure
 
 #else /* HAVE_SHM */
@@ -323,13 +323,13 @@ Lisp_Object Vmemory_signal_data;
 
 /* Buffer in which we save a copy of the C stack at each GC.  */
 
-char *stack_copy;
-int stack_copy_size;
+static char *stack_copy;
+static int stack_copy_size;
 
 /* Non-zero means ignore malloc warnings.  Set during initialization.
    Currently not used.  */
 
-int ignore_warnings;
+static int ignore_warnings;
 
 Lisp_Object Qgc_cons_threshold, Qchar_table_extra_slots;
 
@@ -341,7 +341,9 @@ Lisp_Object Vgc_elapsed;    /* accumulated elapsed time in GC  */
 EMACS_INT gcs_done;            /* accumulated GCs  */
 
 static void mark_buffer P_ ((Lisp_Object));
+static void mark_terminals P_ ((void));
 extern void mark_kboards P_ ((void));
+extern void mark_ttys P_ ((void));
 extern void mark_backtrace P_ ((void));
 static void gc_sweep P_ ((void));
 static void mark_glyph_matrix P_ ((struct glyph_matrix *));
@@ -349,8 +351,6 @@ static void mark_face_cache P_ ((struct face_cache *));
 
 #ifdef HAVE_WINDOW_SYSTEM
 extern void mark_fringe_data P_ ((void));
-static void mark_image P_ ((struct image *));
-static void mark_image_cache P_ ((struct frame *));
 #endif /* HAVE_WINDOW_SYSTEM */
 
 static struct Lisp_String *allocate_string P_ ((void));
@@ -373,14 +373,11 @@ enum mem_type
   MEM_TYPE_MISC,
   MEM_TYPE_SYMBOL,
   MEM_TYPE_FLOAT,
-  /* Keep the following vector-like types together, with
-     MEM_TYPE_WINDOW being the last, and MEM_TYPE_VECTOR the
-     first.  Or change the code of live_vector_p, for instance.  */
-  MEM_TYPE_VECTOR,
-  MEM_TYPE_PROCESS,
-  MEM_TYPE_HASH_TABLE,
-  MEM_TYPE_FRAME,
-  MEM_TYPE_WINDOW
+  /* We used to keep separate mem_types for subtypes of vectors such as
+     process, hash_table, frame, terminal, and window, but we never made
+     use of the distinction, so it only caused source-code complexity
+     and runtime slowdown.  Minor but pointless.  */
+  MEM_TYPE_VECTORLIKE
 };
 
 static POINTER_TYPE *lisp_align_malloc P_ ((size_t, enum mem_type));
@@ -397,12 +394,12 @@ void refill_memory_reserve ();
 /* A unique object in pure space used to make some Lisp objects
    on free lists recognizable in O(1).  */
 
-Lisp_Object Vdead;
+static Lisp_Object Vdead;
 
 #ifdef GC_MALLOC_CHECK
 
 enum mem_type allocated_mem_type;
-int dont_register_blocks;
+static int dont_register_blocks;
 
 #endif /* GC_MALLOC_CHECK */
 
@@ -467,7 +464,7 @@ static struct mem_node mem_z;
 #define MEM_NIL &mem_z
 
 static POINTER_TYPE *lisp_malloc P_ ((size_t, enum mem_type));
-static struct Lisp_Vector *allocate_vectorlike P_ ((EMACS_INT, enum mem_type));
+static struct Lisp_Vector *allocate_vectorlike P_ ((EMACS_INT));
 static void lisp_free P_ ((POINTER_TYPE *));
 static void mark_stack P_ ((void));
 static int live_vector_p P_ ((struct mem_node *, void *));
@@ -502,12 +499,12 @@ struct gcpro *gcprolist;
 /* Addresses of staticpro'd variables.  Initialize it to a nonzero
    value; otherwise some compilers put it into BSS.  */
 
-#define NSTATICS 0x600
-Lisp_Object *staticvec[NSTATICS] = {&Vpurify_flag};
+#define NSTATICS 0x640
+static Lisp_Object *staticvec[NSTATICS] = {&Vpurify_flag};
 
 /* Index of next unused slot in staticvec.  */
 
-int staticidx = 0;
+static int staticidx = 0;
 
 static POINTER_TYPE *pure_alloc P_ ((size_t, int));
 
@@ -743,6 +740,15 @@ overrun_check_free (block)
 #define free overrun_check_free
 #endif
 
+#ifdef SYNC_INPUT
+/* When using SYNC_INPUT, we don't call malloc from a signal handler, so
+   there's no need to block input around malloc.  */
+#define MALLOC_BLOCK_INPUT   ((void)0)
+#define MALLOC_UNBLOCK_INPUT ((void)0)
+#else
+#define MALLOC_BLOCK_INPUT   BLOCK_INPUT
+#define MALLOC_UNBLOCK_INPUT UNBLOCK_INPUT
+#endif
 
 /* Like malloc but check for no memory and block interrupt input..  */
 
@@ -752,9 +758,9 @@ xmalloc (size)
 {
   register POINTER_TYPE *val;
 
-  BLOCK_INPUT;
+  MALLOC_BLOCK_INPUT;
   val = (POINTER_TYPE *) malloc (size);
-  UNBLOCK_INPUT;
+  MALLOC_UNBLOCK_INPUT;
 
   if (!val && size)
     memory_full ();
@@ -771,14 +777,14 @@ xrealloc (block, size)
 {
   register POINTER_TYPE *val;
 
-  BLOCK_INPUT;
+  MALLOC_BLOCK_INPUT;
   /* We must call malloc explicitly when BLOCK is 0, since some
      reallocs don't do this.  */
   if (! block)
     val = (POINTER_TYPE *) malloc (size);
   else
     val = (POINTER_TYPE *) realloc (block, size);
-  UNBLOCK_INPUT;
+  MALLOC_UNBLOCK_INPUT;
 
   if (!val && size) memory_full ();
   return val;
@@ -791,9 +797,11 @@ void
 xfree (block)
      POINTER_TYPE *block;
 {
-  BLOCK_INPUT;
+  if (!block)
+    return;
+  MALLOC_BLOCK_INPUT;
   free (block);
-  UNBLOCK_INPUT;
+  MALLOC_UNBLOCK_INPUT;
   /* We don't call refill_memory_reserve here
      because that duplicates doing so in emacs_blocked_free
      and the criterion should go there.  */
@@ -844,7 +852,7 @@ lisp_malloc (nbytes, type)
 {
   register void *val;
 
-  BLOCK_INPUT;
+  MALLOC_BLOCK_INPUT;
 
 #ifdef GC_MALLOC_CHECK
   allocated_mem_type = type;
@@ -874,7 +882,7 @@ lisp_malloc (nbytes, type)
     mem_insert (val, (char *) val + nbytes, type);
 #endif
 
-  UNBLOCK_INPUT;
+  MALLOC_UNBLOCK_INPUT;
   if (!val && nbytes)
     memory_full ();
   return val;
@@ -887,12 +895,12 @@ static void
 lisp_free (block)
      POINTER_TYPE *block;
 {
-  BLOCK_INPUT;
+  MALLOC_BLOCK_INPUT;
   free (block);
 #if GC_MARK_STACK && !defined GC_MALLOC_CHECK
   mem_delete (mem_find (block));
 #endif
-  UNBLOCK_INPUT;
+  MALLOC_UNBLOCK_INPUT;
 }
 
 /* Allocation of aligned blocks of memory to store Lisp data.              */
@@ -993,7 +1001,7 @@ lisp_align_malloc (nbytes, type)
 
   eassert (nbytes <= BLOCK_BYTES);
 
-  BLOCK_INPUT;
+  MALLOC_BLOCK_INPUT;
 
 #ifdef GC_MALLOC_CHECK
   allocated_mem_type = type;
@@ -1025,7 +1033,7 @@ lisp_align_malloc (nbytes, type)
 
       if (base == 0)
        {
-         UNBLOCK_INPUT;
+         MALLOC_UNBLOCK_INPUT;
          memory_full ();
        }
 
@@ -1051,7 +1059,7 @@ lisp_align_malloc (nbytes, type)
            {
              lisp_malloc_loser = base;
              free (base);
-             UNBLOCK_INPUT;
+             MALLOC_UNBLOCK_INPUT;
              memory_full ();
            }
        }
@@ -1084,7 +1092,7 @@ lisp_align_malloc (nbytes, type)
     mem_insert (val, (char *) val + nbytes, type);
 #endif
 
-  UNBLOCK_INPUT;
+  MALLOC_UNBLOCK_INPUT;
   if (!val && nbytes)
     memory_full ();
 
@@ -1099,7 +1107,7 @@ lisp_align_free (block)
   struct ablock *ablock = block;
   struct ablocks *abase = ABLOCK_ABASE (ablock);
 
-  BLOCK_INPUT;
+  MALLOC_BLOCK_INPUT;
 #if GC_MARK_STACK && !defined GC_MALLOC_CHECK
   mem_delete (mem_find (block));
 #endif
@@ -1132,7 +1140,7 @@ lisp_align_free (block)
 #endif
       free (ABLOCKS_BASE (abase));
     }
-  UNBLOCK_INPUT;
+  MALLOC_UNBLOCK_INPUT;
 }
 
 /* Return a new buffer structure allocated from the heap with
@@ -1144,6 +1152,8 @@ allocate_buffer ()
   struct buffer *b
     = (struct buffer *) lisp_malloc (sizeof (struct buffer),
                                     MEM_TYPE_BUFFER);
+  b->size = sizeof (struct buffer) / sizeof (EMACS_INT);
+  XSETPVECTYPE (b, PVEC_BUFFER);
   return b;
 }
 
@@ -1161,6 +1171,8 @@ allocate_buffer ()
    can use GNU malloc.  */
 
 #ifndef SYNC_INPUT
+/* When using SYNC_INPUT, we don't call malloc from a signal handler, so
+   there's no need to block input around malloc.  */
 
 #ifndef DOUG_LEA_MALLOC
 extern void * (*__malloc_hook) P_ ((size_t, const void *));
@@ -1179,8 +1191,6 @@ emacs_blocked_free (ptr, ptr2)
      void *ptr;
      const void *ptr2;
 {
-  EMACS_INT bytes_used_now;
-
   BLOCK_INPUT_ALLOC;
 
 #ifdef GC_MALLOC_CHECK
@@ -1236,7 +1246,8 @@ emacs_blocked_malloc (size, ptr)
   BLOCK_INPUT_ALLOC;
   __malloc_hook = old_malloc_hook;
 #ifdef DOUG_LEA_MALLOC
-    mallopt (M_TOP_PAD, malloc_hysteresis * 4096);
+  /* Segfaults on my system.  --lorentey */
+  /* mallopt (M_TOP_PAD, malloc_hysteresis * 4096); */
 #else
     __malloc_extra_blocks = malloc_hysteresis;
 #endif
@@ -1342,9 +1353,9 @@ emacs_blocked_realloc (ptr, size, ptr2)
 void
 reset_malloc_hooks ()
 {
-  __free_hook = 0;
-  __malloc_hook = 0;
-  __realloc_hook = 0;
+  __free_hook = old_free_hook;
+  __malloc_hook = old_malloc_hook;
+  __realloc_hook = old_realloc_hook;
 }
 #endif /* HAVE_GTK_AND_PTHREAD */
 
@@ -1355,6 +1366,7 @@ void
 uninterrupt_malloc ()
 {
 #ifdef HAVE_GTK_AND_PTHREAD
+#ifdef DOUG_LEA_MALLOC
   pthread_mutexattr_t attr;
 
   /*  GLIBC has a faster way to do this, but lets keep it portable.
@@ -1362,6 +1374,11 @@ uninterrupt_malloc ()
   pthread_mutexattr_init (&attr);
   pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
   pthread_mutex_init (&alloc_mutex, &attr);
+#else  /* !DOUG_LEA_MALLOC */
+  /* Some systems such as Solaris 2.6 doesn't have a recursive mutex,
+     and the bundled gmalloc.c doesn't require it.  */
+  pthread_mutex_init (&alloc_mutex, NULL);
+#endif /* !DOUG_LEA_MALLOC */
 #endif /* HAVE_GTK_AND_PTHREAD */
 
   if (__free_hook != emacs_blocked_free)
@@ -1405,7 +1422,7 @@ struct interval_block
 /* Current interval block.  Its `next' pointer points to older
    blocks.  */
 
-struct interval_block *interval_block;
+static struct interval_block *interval_block;
 
 /* Index in interval_block above of the next unused interval
    structure.  */
@@ -1422,7 +1439,7 @@ INTERVAL interval_free_list;
 
 /* Total number of interval blocks now in use.  */
 
-int n_interval_blocks;
+static int n_interval_blocks;
 
 
 /* Initialize interval allocation.  */
@@ -1446,9 +1463,7 @@ make_interval ()
 
   /* eassert (!handling_signal); */
 
-#ifndef SYNC_INPUT
-  BLOCK_INPUT;
-#endif
+  MALLOC_BLOCK_INPUT;
 
   if (interval_free_list)
     {
@@ -1472,9 +1487,7 @@ make_interval ()
       val = &interval_block->intervals[interval_block_index++];
     }
 
-#ifndef SYNC_INPUT
-  UNBLOCK_INPUT;
-#endif
+  MALLOC_UNBLOCK_INPUT;
 
   consing_since_gc += sizeof (struct interval);
   intervals_consed++;
@@ -1528,7 +1541,7 @@ mark_interval_tree (tree)
   } while (0)
 
 \f
-/* Number support.  If NO_UNION_TYPE isn't in effect, we
+/* Number support.  If USE_LISP_UNION_TYPE is in effect, we
    can't create number objects in macros.  */
 #ifndef make_number
 Lisp_Object
@@ -1748,7 +1761,7 @@ static char string_overrun_cookie[GC_STRING_OVERRUN_COOKIE_SIZE] =
 
 /* Initialize string allocation.  Called from init_alloc_once.  */
 
-void
+static void
 init_strings ()
 {
   total_strings = total_free_strings = total_string_size = 0;
@@ -1756,6 +1769,8 @@ init_strings ()
   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);
 }
 
 
@@ -1763,8 +1778,8 @@ init_strings ()
 
 static int check_string_bytes_count;
 
-void check_string_bytes P_ ((int));
-void check_sblock P_ ((struct sblock *));
+static void check_string_bytes P_ ((int));
+static void check_sblock P_ ((struct sblock *));
 
 #define CHECK_STRING_BYTES(S)  STRING_BYTES (S)
 
@@ -1785,7 +1800,7 @@ string_bytes (s)
 
 /* Check validity of Lisp strings' string_bytes member in B.  */
 
-void
+static void
 check_sblock (b)
      struct sblock *b;
 {
@@ -1819,7 +1834,7 @@ check_sblock (b)
    non-zero means check all strings, otherwise check only most
    recently allocated strings.  Used for hunting a bug.  */
 
-void
+static void
 check_string_bytes (all_p)
      int all_p;
 {
@@ -1875,9 +1890,7 @@ allocate_string ()
 
   /* eassert (!handling_signal); */
 
-#ifndef SYNC_INPUT
-  BLOCK_INPUT;
-#endif
+  MALLOC_BLOCK_INPUT;
 
   /* If the free-list is empty, allocate a new string_block, and
      add all the Lisp_Strings in it to the free-list.  */
@@ -1908,9 +1921,7 @@ allocate_string ()
   s = string_free_list;
   string_free_list = NEXT_FREE_LISP_STRING (s);
 
-#ifndef SYNC_INPUT
-  UNBLOCK_INPUT;
-#endif
+  MALLOC_UNBLOCK_INPUT;
 
   /* Probably not strictly necessary, but play it safe.  */
   bzero (s, sizeof *s);
@@ -1921,11 +1932,7 @@ allocate_string ()
   consing_since_gc += sizeof *s;
 
 #ifdef GC_CHECK_STRING_BYTES
-  if (!noninteractive
-#ifdef MAC_OS8
-      && current_sblock
-#endif
-     )
+  if (!noninteractive)
     {
       if (++check_string_bytes_count == 200)
        {
@@ -1962,9 +1969,7 @@ allocate_string_data (s, nchars, nbytes)
   old_data = s->data ? SDATA_OF_STRING (s) : NULL;
   old_nbytes = GC_STRING_BYTES (s);
 
-#ifndef SYNC_INPUT
-  BLOCK_INPUT;
-#endif
+  MALLOC_BLOCK_INPUT;
 
   if (nbytes > LARGE_STRING_BYTES)
     {
@@ -1980,18 +1985,14 @@ allocate_string_data (s, nchars, nbytes)
          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  */
-      BLOCK_INPUT;
       mallopt (M_MMAP_MAX, 0);
-      UNBLOCK_INPUT;
 #endif
 
       b = (struct sblock *) lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP);
 
 #ifdef DOUG_LEA_MALLOC
       /* Back to a reasonable maximum of mmap'ed areas. */
-      BLOCK_INPUT;
       mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
-      UNBLOCK_INPUT;
 #endif
 
       b->next_free = &b->first_data;
@@ -2022,9 +2023,7 @@ allocate_string_data (s, nchars, nbytes)
   data = b->next_free;
   b->next_free = (struct sdata *) ((char *) data + needed + GC_STRING_EXTRA);
 
-#ifndef SYNC_INPUT
-  UNBLOCK_INPUT;
-#endif
+  MALLOC_UNBLOCK_INPUT;
 
   data->string = s;
   s->data = SDATA_DATA (data);
@@ -2342,11 +2341,13 @@ LENGTH must be a number.  INIT matters only in whether it is t or nil.  */)
   /* We must allocate one more elements than LENGTH_IN_ELTS for the
      slot `size' of the struct Lisp_Bool_Vector.  */
   val = Fmake_vector (make_number (length_in_elts + 1), Qnil);
-  p = XBOOL_VECTOR (val);
 
   /* Get rid of any bits that would cause confusion.  */
-  p->vector_size = 0;
-  XSETBOOL_VECTOR (val, p);
+  XVECTOR (val)->size = 0;     /* No Lisp_Object to trace in there.  */
+  /* Use  XVECTOR (val) rather than `p' because p->size is not TRT. */
+  XSETPVECTYPE (XVECTOR (val), PVEC_BOOL_VECTOR);
+
+  p = XBOOL_VECTOR (val);
   p->size = XFASTINT (length);
 
   real_init = (NILP (init) ? 0 : -1);
@@ -2355,7 +2356,7 @@ LENGTH must be a number.  INIT matters only in whether it is t or nil.  */)
 
   /* Clear the extraneous bits in the last byte.  */
   if (XINT (length) != length_in_chars * BOOL_VECTOR_BITS_PER_CHAR)
-    XBOOL_VECTOR (val)->data[length_in_chars - 1]
+    p->data[length_in_chars - 1]
       &= (1 << (XINT (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1;
 
   return val;
@@ -2479,6 +2480,9 @@ make_uninit_string (length)
      int length;
 {
   Lisp_Object val;
+
+  if (!length)
+    return empty_unibyte_string;
   val = make_uninit_multibyte_string (length, length);
   STRING_SET_UNIBYTE (val);
   return val;
@@ -2497,6 +2501,8 @@ make_uninit_multibyte_string (nchars, nbytes)
 
   if (nchars < 0)
     abort ();
+  if (!nbytes)
+    return empty_multibyte_string;
 
   s = allocate_string ();
   allocate_string_data (s, nchars, nbytes);
@@ -2577,7 +2583,7 @@ struct Lisp_Float *float_free_list;
 
 /* Initialize float allocation.  */
 
-void
+static void
 init_float ()
 {
   float_block = NULL;
@@ -2589,7 +2595,7 @@ init_float ()
 
 /* Explicitly free a float cell by putting it on the free-list.  */
 
-void
+static void
 free_float (ptr)
      struct Lisp_Float *ptr;
 {
@@ -2608,9 +2614,7 @@ make_float (float_value)
 
   /* eassert (!handling_signal); */
 
-#ifndef SYNC_INPUT
-  BLOCK_INPUT;
-#endif
+  MALLOC_BLOCK_INPUT;
 
   if (float_free_list)
     {
@@ -2637,9 +2641,7 @@ make_float (float_value)
       float_block_index++;
     }
 
-#ifndef SYNC_INPUT
-  UNBLOCK_INPUT;
-#endif
+  MALLOC_UNBLOCK_INPUT;
 
   XFLOAT_DATA (val) = float_value;
   eassert (!FLOAT_MARKED_P (XFLOAT (val)));
@@ -2700,12 +2702,12 @@ struct Lisp_Cons *cons_free_list;
 
 /* Total number of cons blocks now in use.  */
 
-int n_cons_blocks;
+static int n_cons_blocks;
 
 
 /* Initialize cons allocation.  */
 
-void
+static void
 init_cons ()
 {
   cons_block = NULL;
@@ -2737,9 +2739,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
 
   /* eassert (!handling_signal); */
 
-#ifndef SYNC_INPUT
-  BLOCK_INPUT;
-#endif
+  MALLOC_BLOCK_INPUT;
 
   if (cons_free_list)
     {
@@ -2765,9 +2765,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
       cons_block_index++;
     }
 
-#ifndef SYNC_INPUT
-  UNBLOCK_INPUT;
-#endif
+  MALLOC_UNBLOCK_INPUT;
 
   XSETCAR (val, car);
   XSETCDR (val, cdr);
@@ -2906,59 +2904,50 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0,
 
 /* Singly-linked list of all vectors.  */
 
-struct Lisp_Vector *all_vectors;
+static struct Lisp_Vector *all_vectors;
 
 /* Total number of vector-like objects now in use.  */
 
-int n_vectors;
+static int n_vectors;
 
 
 /* Value is a pointer to a newly allocated Lisp_Vector structure
    with room for LEN Lisp_Objects.  */
 
 static struct Lisp_Vector *
-allocate_vectorlike (len, type)
+allocate_vectorlike (len)
      EMACS_INT len;
-     enum mem_type type;
 {
   struct Lisp_Vector *p;
   size_t nbytes;
 
+  MALLOC_BLOCK_INPUT;
+
 #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.  */
-  BLOCK_INPUT;
   mallopt (M_MMAP_MAX, 0);
-  UNBLOCK_INPUT;
 #endif
 
   /* This gets triggered by code which I haven't bothered to fix.  --Stef  */
   /* eassert (!handling_signal); */
 
   nbytes = sizeof *p + (len - 1) * sizeof p->contents[0];
-  p = (struct Lisp_Vector *) lisp_malloc (nbytes, type);
+  p = (struct Lisp_Vector *) lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE);
 
 #ifdef DOUG_LEA_MALLOC
   /* Back to a reasonable maximum of mmap'ed areas.  */
-  BLOCK_INPUT;
   mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
-  UNBLOCK_INPUT;
 #endif
 
   consing_since_gc += nbytes;
   vector_cells_consed += len;
 
-#ifndef SYNC_INPUT
-  BLOCK_INPUT;
-#endif
-
   p->next = all_vectors;
   all_vectors = p;
 
-#ifndef SYNC_INPUT
-  UNBLOCK_INPUT;
-#endif
+  MALLOC_UNBLOCK_INPUT;
 
   ++n_vectors;
   return p;
@@ -2971,7 +2960,7 @@ struct Lisp_Vector *
 allocate_vector (nslots)
      EMACS_INT nslots;
 {
-  struct Lisp_Vector *v = allocate_vectorlike (nslots, MEM_TYPE_VECTOR);
+  struct Lisp_Vector *v = allocate_vectorlike (nslots);
   v->size = nslots;
   return v;
 }
@@ -2979,81 +2968,65 @@ allocate_vector (nslots)
 
 /* Allocate other vector-like structures.  */
 
-struct Lisp_Hash_Table *
-allocate_hash_table ()
+struct Lisp_Vector *
+allocate_pseudovector (memlen, lisplen, tag)
+     int memlen, lisplen;
+     EMACS_INT tag;
 {
-  EMACS_INT len = VECSIZE (struct Lisp_Hash_Table);
-  struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_HASH_TABLE);
+  struct Lisp_Vector *v = allocate_vectorlike (memlen);
   EMACS_INT i;
 
-  v->size = len;
-  for (i = 0; i < len; ++i)
+  /* Only the first lisplen slots will be traced normally by the GC.  */
+  v->size = lisplen;
+  for (i = 0; i < lisplen; ++i)
     v->contents[i] = Qnil;
 
-  return (struct Lisp_Hash_Table *) v;
+  XSETPVECTYPE (v, tag);       /* Add the appropriate tag.  */
+  return v;
+}
+
+struct Lisp_Hash_Table *
+allocate_hash_table (void)
+{
+  return ALLOCATE_PSEUDOVECTOR (struct Lisp_Hash_Table, count, PVEC_HASH_TABLE);
 }
 
 
 struct window *
 allocate_window ()
 {
-  EMACS_INT len = VECSIZE (struct window);
-  struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_WINDOW);
-  EMACS_INT i;
+  return ALLOCATE_PSEUDOVECTOR(struct window, current_matrix, PVEC_WINDOW);
+}
 
-  for (i = 0; i < len; ++i)
-    v->contents[i] = Qnil;
-  v->size = len;
 
-  return (struct window *) v;
-}
+struct terminal *
+allocate_terminal ()
+{
+  struct terminal *t = ALLOCATE_PSEUDOVECTOR (struct terminal,
+                                             next_terminal, PVEC_TERMINAL);
+  /* Zero out the non-GC'd fields.  FIXME: This should be made unnecessary.  */
+  bzero (&(t->next_terminal),
+        ((char*)(t+1)) - ((char*)&(t->next_terminal)));
 
+  return t;
+}
 
 struct frame *
 allocate_frame ()
 {
-  EMACS_INT len = VECSIZE (struct frame);
-  struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_FRAME);
-  EMACS_INT i;
-
-  for (i = 0; i < len; ++i)
-    v->contents[i] = make_number (0);
-  v->size = len;
-  return (struct frame *) v;
+  struct frame *f = ALLOCATE_PSEUDOVECTOR (struct frame,
+                                          face_cache, PVEC_FRAME);
+  /* Zero out the non-GC'd fields.  FIXME: This should be made unnecessary.  */
+  bzero (&(f->face_cache),
+        ((char*)(f+1)) - ((char*)&(f->face_cache)));
+  return f;
 }
 
 
 struct Lisp_Process *
 allocate_process ()
 {
-  /* Memory-footprint of the object in nb of Lisp_Object fields.  */
-  EMACS_INT memlen = VECSIZE (struct Lisp_Process);
-  /* Size if we only count the actual Lisp_Object fields (which need to be
-     traced by the GC).  */
-  EMACS_INT lisplen = PSEUDOVECSIZE (struct Lisp_Process, pid);
-  struct Lisp_Vector *v = allocate_vectorlike (memlen, MEM_TYPE_PROCESS);
-  EMACS_INT i;
-
-  for (i = 0; i < lisplen; ++i)
-    v->contents[i] = Qnil;
-  v->size = lisplen;
-
-  return (struct Lisp_Process *) v;
-}
-
-
-struct Lisp_Vector *
-allocate_other_vector (len)
-     EMACS_INT len;
-{
-  struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_VECTOR);
-  EMACS_INT i;
-
-  for (i = 0; i < len; ++i)
-    v->contents[i] = Qnil;
-  v->size = len;
-
-  return v;
+  return ALLOCATE_PSEUDOVECTOR (struct Lisp_Process, pid, PVEC_PROCESS);
 }
 
 
@@ -3137,6 +3110,7 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT
        args[index] = Fpurecopy (args[index]);
       p->contents[index] = args[index];
     }
+  XSETPVECTYPE (p, PVEC_COMPILED);
   XSETCOMPILED (val, p);
   return val;
 }
@@ -3164,21 +3138,21 @@ struct symbol_block
 /* Current symbol block and index of first unused Lisp_Symbol
    structure in it.  */
 
-struct symbol_block *symbol_block;
-int symbol_block_index;
+static struct symbol_block *symbol_block;
+static int symbol_block_index;
 
 /* List of free symbols.  */
 
-struct Lisp_Symbol *symbol_free_list;
+static struct Lisp_Symbol *symbol_free_list;
 
 /* Total number of symbol blocks now in use.  */
 
-int n_symbol_blocks;
+static int n_symbol_blocks;
 
 
 /* Initialize symbol allocation.  */
 
-void
+static void
 init_symbol ()
 {
   symbol_block = NULL;
@@ -3201,9 +3175,7 @@ Its value and function definition are void, and its property list is nil.  */)
 
   /* eassert (!handling_signal); */
 
-#ifndef SYNC_INPUT
-  BLOCK_INPUT;
-#endif
+  MALLOC_BLOCK_INPUT;
 
   if (symbol_free_list)
     {
@@ -3226,9 +3198,7 @@ Its value and function definition are void, and its property list is nil.  */)
       symbol_block_index++;
     }
 
-#ifndef SYNC_INPUT
-  UNBLOCK_INPUT;
-#endif
+  MALLOC_UNBLOCK_INPUT;
 
   p = XSYMBOL (val);
   p->xname = name;
@@ -3264,16 +3234,16 @@ struct marker_block
   struct marker_block *next;
 };
 
-struct marker_block *marker_block;
-int marker_block_index;
+static struct marker_block *marker_block;
+static int marker_block_index;
 
-union Lisp_Misc *marker_free_list;
+static union Lisp_Misc *marker_free_list;
 
 /* Total number of marker blocks now in use.  */
 
-int n_marker_blocks;
+static int n_marker_blocks;
 
-void
+static void
 init_marker ()
 {
   marker_block = NULL;
@@ -3291,9 +3261,7 @@ allocate_misc ()
 
   /* eassert (!handling_signal); */
 
-#ifndef SYNC_INPUT
-  BLOCK_INPUT;
-#endif
+  MALLOC_BLOCK_INPUT;
 
   if (marker_free_list)
     {
@@ -3317,14 +3285,12 @@ allocate_misc ()
       marker_block_index++;
     }
 
-#ifndef SYNC_INPUT
-  UNBLOCK_INPUT;
-#endif
+  MALLOC_UNBLOCK_INPUT;
 
   --total_free_markers;
   consing_since_gc += sizeof (union Lisp_Misc);
   misc_objects_consed++;
-  XMARKER (val)->gcmarkbit = 0;
+  XMISCANY (val)->gcmarkbit = 0;
   return val;
 }
 
@@ -3334,7 +3300,7 @@ void
 free_misc (misc)
      Lisp_Object misc;
 {
-  XMISC (misc)->u_marker.type = Lisp_Misc_Free;
+  XMISCTYPE (misc) = Lisp_Misc_Free;
   XMISC (misc)->u_free.chain = marker_free_list;
   marker_free_list = XMISC (misc);
 
@@ -3572,9 +3538,9 @@ mem_insert (start, end, type)
 {
   struct mem_node *c, *parent, *x;
 
-  if (start < min_heap_address)
+  if (min_heap_address == NULL || start < min_heap_address)
     min_heap_address = start;
-  if (end > max_heap_address)
+  if (max_heap_address == NULL || end > max_heap_address)
     max_heap_address = end;
 
   /* See where in the tree a node for START belongs.  In this
@@ -4050,7 +4016,7 @@ live_misc_p (m, p)
              && offset < (MARKER_BLOCK_SIZE * sizeof b->markers[0])
              && (b != marker_block
                  || offset / sizeof b->markers[0] < marker_block_index)
-             && ((union Lisp_Misc *) p)->u_marker.type != Lisp_Misc_Free);
+             && ((union Lisp_Misc *) p)->u_any.type != Lisp_Misc_Free);
     }
   else
     return 0;
@@ -4065,9 +4031,7 @@ live_vector_p (m, p)
      struct mem_node *m;
      void *p;
 {
-  return (p == m->start
-         && m->type >= MEM_TYPE_VECTOR
-         && m->type <= MEM_TYPE_WINDOW);
+  return (p == m->start && m->type == MEM_TYPE_VECTORLIKE);
 }
 
 
@@ -4153,7 +4117,7 @@ mark_maybe_object (obj)
     {
       int mark_p = 0;
 
-      switch (XGCTYPE (obj))
+      switch (XTYPE (obj))
        {
        case Lisp_String:
          mark_p = (live_string_p (m, po)
@@ -4173,17 +4137,17 @@ mark_maybe_object (obj)
          break;
 
        case Lisp_Vectorlike:
-         /* Note: can't check GC_BUFFERP before we know it's a
+         /* Note: can't check BUFFERP before we know it's a
             buffer because checking that dereferences the pointer
             PO which might point anywhere.  */
          if (live_vector_p (m, po))
-           mark_p = !GC_SUBRP (obj) && !VECTOR_MARKED_P (XVECTOR (obj));
+           mark_p = !SUBRP (obj) && !VECTOR_MARKED_P (XVECTOR (obj));
          else if (live_buffer_p (m, po))
-           mark_p = GC_BUFFERP (obj) && !VECTOR_MARKED_P (XBUFFER (obj));
+           mark_p = BUFFERP (obj) && !VECTOR_MARKED_P (XBUFFER (obj));
          break;
 
        case Lisp_Misc:
-         mark_p = (live_misc_p (m, po) && !XMARKER (obj)->gcmarkbit);
+         mark_p = (live_misc_p (m, po) && !XMISCANY (obj)->gcmarkbit);
          break;
 
        case Lisp_Int:
@@ -4213,9 +4177,14 @@ mark_maybe_pointer (p)
 {
   struct mem_node *m;
 
-  /* Quickly rule out some values which can't point to Lisp data.  We
-     assume that Lisp data is aligned on even addresses.  */
-  if ((EMACS_INT) p & 1)
+  /* Quickly rule out some values which can't point to Lisp data.  */
+  if ((EMACS_INT) p %
+#ifdef USE_LSB_TAG
+      8 /* USE_LSB_TAG needs Lisp data to be aligned on multiples of 8.  */
+#else
+      2 /* We assume that Lisp data is aligned on even addresses.  */
+#endif
+      )
     return;
 
   m = mem_find (p);
@@ -4260,16 +4229,12 @@ mark_maybe_pointer (p)
            XSETFLOAT (obj, p);
          break;
 
-       case MEM_TYPE_VECTOR:
-       case MEM_TYPE_PROCESS:
-       case MEM_TYPE_HASH_TABLE:
-       case MEM_TYPE_FRAME:
-       case MEM_TYPE_WINDOW:
+       case MEM_TYPE_VECTORLIKE:
          if (live_vector_p (m, p))
            {
              Lisp_Object tem;
              XSETVECTOR (tem, p);
-             if (!GC_SUBRP (tem) && !VECTOR_MARKED_P (XVECTOR (tem)))
+             if (!SUBRP (tem) && !VECTOR_MARKED_P (XVECTOR (tem)))
                obj = tem;
            }
          break;
@@ -4278,7 +4243,7 @@ mark_maybe_pointer (p)
          abort ();
        }
 
-      if (!GC_NILP (obj))
+      if (!NILP (obj))
        mark_object (obj);
     }
 }
@@ -4522,7 +4487,7 @@ mark_stack ()
   /* Fixme: Code in the Boehm GC suggests flushing (with `flushrs') is
      needed on ia64 too.  See mach_dep.c, where it also says inline
      assembler doesn't work with relevant proprietary compilers.  */
-#ifdef sparc
+#ifdef __sparc__
   asm ("ta 3");
 #endif
 
@@ -4575,7 +4540,7 @@ mark_stack ()
 
 
 /* Determine whether it is safe to access memory at address P.  */
-int
+static int
 valid_pointer_p (p)
      void *p;
 {
@@ -4664,11 +4629,7 @@ valid_lisp_object_p (obj)
     case MEM_TYPE_FLOAT:
       return live_float_p (m, p);
 
-    case MEM_TYPE_VECTOR:
-    case MEM_TYPE_PROCESS:
-    case MEM_TYPE_HASH_TABLE:
-    case MEM_TYPE_FRAME:
-    case MEM_TYPE_WINDOW:
+    case MEM_TYPE_VECTORLIKE:
       return live_vector_p (m, p);
 
     default:
@@ -4875,7 +4836,7 @@ pure_cons (car, cdr)
 
 /* Value is a float object with value NUM allocated from pure space.  */
 
-Lisp_Object
+static Lisp_Object
 make_pure_float (num)
      double num;
 {
@@ -4941,7 +4902,10 @@ Does not copy symbols.  Copies strings without text properties.  */)
       for (i = 0; i < size; i++)
        vec->contents[i] = Fpurecopy (XVECTOR (obj)->contents[i]);
       if (COMPILEDP (obj))
-       XSETCOMPILED (obj, vec);
+       {
+         XSETPVECTYPE (vec, PVEC_COMPILED);
+         XSETCOMPILED (obj, vec);
+       }
       else
        XSETVECTOR (obj, vec);
       return obj;
@@ -5118,7 +5082,9 @@ returns nil, because real GC can't be done.  */)
       mark_object (bind->symbol);
       mark_object (bind->old_value);
     }
+  mark_terminals ();
   mark_kboards ();
+  mark_ttys ();
 
 #ifdef USE_GTK
   {
@@ -5181,8 +5147,8 @@ returns nil, because real GC can't be done.  */)
            prev = Qnil;
            while (CONSP (tail))
              {
-               if (GC_CONSP (XCAR (tail))
-                   && GC_MARKERP (XCAR (XCAR (tail)))
+               if (CONSP (XCAR (tail))
+                   && MARKERP (XCAR (XCAR (tail)))
                    && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit)
                  {
                    if (NILP (prev))
@@ -5331,7 +5297,7 @@ mark_glyph_matrix (matrix)
            struct glyph *end_glyph = glyph + row->used[area];
 
            for (; glyph < end_glyph; ++glyph)
-             if (GC_STRINGP (glyph->object)
+             if (STRINGP (glyph->object)
                  && !STRING_MARKED_P (XSTRING (glyph->object)))
                mark_object (glyph->object);
          }
@@ -5362,48 +5328,43 @@ mark_face_cache (c)
 }
 
 
-#ifdef HAVE_WINDOW_SYSTEM
-
-/* Mark Lisp objects in image IMG.  */
-
-static void
-mark_image (img)
-     struct image *img;
-{
-  mark_object (img->spec);
-
-  if (!NILP (img->data.lisp_val))
-    mark_object (img->data.lisp_val);
-}
-
-
-/* Mark Lisp objects in image cache of frame F.  It's done this way so
-   that we don't have to include xterm.h here.  */
-
-static void
-mark_image_cache (f)
-     struct frame *f;
-{
-  forall_images_in_image_cache (f, mark_image);
-}
-
-#endif /* HAVE_X_WINDOWS */
-
-
 \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.  */
 
 #define LAST_MARKED_SIZE 500
-Lisp_Object last_marked[LAST_MARKED_SIZE];
+static Lisp_Object last_marked[LAST_MARKED_SIZE];
 int last_marked_index;
 
 /* For debugging--call abort when we cdr down this many
    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.  */
-int mark_object_loop_halt;
+static int mark_object_loop_halt;
+
+/* Return non-zero if the object was not yet marked.  */
+static int
+mark_vectorlike (ptr)
+     struct Lisp_Vector *ptr;
+{
+  register EMACS_INT size = ptr->size;
+  register int i;
+
+  if (VECTOR_MARKED_P (ptr))
+    return 0;                  /* Already marked */
+  VECTOR_MARK (ptr);           /* Else mark it */
+  if (size & PSEUDOVECTOR_FLAG)
+    size &= PSEUDOVECTOR_SIZE_MASK;
+
+  /* Note that this size is not the memory-footprint size, but only
+     the number of Lisp_Object fields that we should trace.
+     The distinction is used e.g. by Lisp_Process which places extra
+     non-Lisp_Object fields at the end of the structure.  */
+  for (i = 0; i < size; i++) /* and then mark its elements */
+    mark_object (ptr->contents[i]);
+  return 1;
+}
 
 void
 mark_object (arg)
@@ -5464,7 +5425,7 @@ mark_object (arg)
 
 #endif /* not GC_CHECK_MARKED_OBJECTS */
 
-  switch (SWITCH_ENUM_CAST (XGCTYPE (obj)))
+  switch (SWITCH_ENUM_CAST (XTYPE (obj)))
     {
     case Lisp_String:
       {
@@ -5483,13 +5444,13 @@ mark_object (arg)
     case Lisp_Vectorlike:
 #ifdef GC_CHECK_MARKED_OBJECTS
       m = mem_find (po);
-      if (m == MEM_NIL && !GC_SUBRP (obj)
+      if (m == MEM_NIL && !SUBRP (obj)
          && po != &buffer_defaults
          && po != &buffer_local_symbols)
        abort ();
 #endif /* GC_CHECK_MARKED_OBJECTS */
 
-      if (GC_BUFFERP (obj))
+      if (BUFFERP (obj))
        {
          if (!VECTOR_MARKED_P (XBUFFER (obj)))
            {
@@ -5506,9 +5467,9 @@ mark_object (arg)
              mark_buffer (obj);
            }
        }
-      else if (GC_SUBRP (obj))
+      else if (SUBRP (obj))
        break;
-      else if (GC_COMPILEDP (obj))
+      else if (COMPILEDP (obj))
        /* We could treat this just like a vector, but it is better to
           save the COMPILED_CONSTANTS element for last and avoid
           recursion there.  */
@@ -5531,132 +5492,44 @@ mark_object (arg)
          obj = ptr->contents[COMPILED_CONSTANTS];
          goto loop;
        }
-      else if (GC_FRAMEP (obj))
+      else if (FRAMEP (obj))
        {
          register struct frame *ptr = XFRAME (obj);
-
-         if (VECTOR_MARKED_P (ptr)) break;   /* Already marked */
-         VECTOR_MARK (ptr);                  /* Else mark it */
-
-         CHECK_LIVE (live_vector_p);
-         mark_object (ptr->name);
-         mark_object (ptr->icon_name);
-         mark_object (ptr->title);
-         mark_object (ptr->focus_frame);
-         mark_object (ptr->selected_window);
-         mark_object (ptr->minibuffer_window);
-         mark_object (ptr->param_alist);
-         mark_object (ptr->scroll_bars);
-         mark_object (ptr->condemned_scroll_bars);
-         mark_object (ptr->menu_bar_items);
-         mark_object (ptr->face_alist);
-         mark_object (ptr->menu_bar_vector);
-         mark_object (ptr->buffer_predicate);
-         mark_object (ptr->buffer_list);
-         mark_object (ptr->menu_bar_window);
-         mark_object (ptr->tool_bar_window);
-         mark_face_cache (ptr->face_cache);
-#ifdef HAVE_WINDOW_SYSTEM
-         mark_image_cache (ptr);
-         mark_object (ptr->tool_bar_items);
-         mark_object (ptr->desired_tool_bar_string);
-         mark_object (ptr->current_tool_bar_string);
-#endif /* HAVE_WINDOW_SYSTEM */
-       }
-      else if (GC_BOOL_VECTOR_P (obj))
-       {
-         register struct Lisp_Vector *ptr = XVECTOR (obj);
-
-         if (VECTOR_MARKED_P (ptr))
-           break;   /* Already marked */
-         CHECK_LIVE (live_vector_p);
-         VECTOR_MARK (ptr);    /* Else mark it */
+         if (mark_vectorlike (XVECTOR (obj)))
+           mark_face_cache (ptr->face_cache);
        }
-      else if (GC_WINDOWP (obj))
+      else if (WINDOWP (obj))
        {
          register struct Lisp_Vector *ptr = XVECTOR (obj);
          struct window *w = XWINDOW (obj);
-         register int i;
-
-         /* Stop if already marked.  */
-         if (VECTOR_MARKED_P (ptr))
-           break;
-
-         /* Mark it.  */
-         CHECK_LIVE (live_vector_p);
-         VECTOR_MARK (ptr);
-
-         /* There is no Lisp data above The member CURRENT_MATRIX in
-            struct WINDOW.  Stop marking when that slot is reached.  */
-         for (i = 0;
-              (char *) &ptr->contents[i] < (char *) &w->current_matrix;
-              i++)
-           mark_object (ptr->contents[i]);
-
-         /* Mark glyphs for leaf windows.  Marking window matrices is
-            sufficient because frame matrices use the same glyph
-            memory.  */
-         if (NILP (w->hchild)
-             && NILP (w->vchild)
-             && w->current_matrix)
+         if (mark_vectorlike (ptr))
            {
-             mark_glyph_matrix (w->current_matrix);
-             mark_glyph_matrix (w->desired_matrix);
+             /* Mark glyphs for leaf windows.  Marking window matrices is
+                sufficient because frame matrices use the same glyph
+                memory.  */
+             if (NILP (w->hchild)
+                 && NILP (w->vchild)
+                 && w->current_matrix)
+               {
+                 mark_glyph_matrix (w->current_matrix);
+                 mark_glyph_matrix (w->desired_matrix);
+               }
            }
        }
-      else if (GC_HASH_TABLE_P (obj))
+      else if (HASH_TABLE_P (obj))
        {
          struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
-
-         /* Stop if already marked.  */
-         if (VECTOR_MARKED_P (h))
-           break;
-
-         /* Mark it.  */
-         CHECK_LIVE (live_vector_p);
-         VECTOR_MARK (h);
-
-         /* Mark contents.  */
-         /* Do not mark next_free or next_weak.
-            Being in the next_weak chain
-            should not keep the hash table alive.
-            No need to mark `count' since it is an integer.  */
-         mark_object (h->test);
-         mark_object (h->weak);
-         mark_object (h->rehash_size);
-         mark_object (h->rehash_threshold);
-         mark_object (h->hash);
-         mark_object (h->next);
-         mark_object (h->index);
-         mark_object (h->user_hash_function);
-         mark_object (h->user_cmp_function);
-
-         /* If hash table is not weak, mark all keys and values.
-            For weak tables, mark only the vector.  */
-         if (GC_NILP (h->weak))
-           mark_object (h->key_and_value);
-         else
-           VECTOR_MARK (XVECTOR (h->key_and_value));
+         if (mark_vectorlike ((struct Lisp_Vector *)h))
+           { /* If hash table is not weak, mark all keys and values.
+                For weak tables, mark only the vector.  */
+             if (NILP (h->weak))
+               mark_object (h->key_and_value);
+             else
+               VECTOR_MARK (XVECTOR (h->key_and_value));
+           }
        }
       else
-       {
-         register struct Lisp_Vector *ptr = XVECTOR (obj);
-         register EMACS_INT size = ptr->size;
-         register int i;
-
-         if (VECTOR_MARKED_P (ptr)) break; /* Already marked */
-         CHECK_LIVE (live_vector_p);
-         VECTOR_MARK (ptr);    /* Else mark it */
-         if (size & PSEUDOVECTOR_FLAG)
-           size &= PSEUDOVECTOR_SIZE_MASK;
-
-         /* Note that this size is not the memory-footprint size, but only
-            the number of Lisp_Object fields that we should trace.
-            The distinction is used e.g. by Lisp_Process which places extra
-            non-Lisp_Object fields at the end of the structure.  */
-         for (i = 0; i < size; i++) /* and then mark its elements */
-           mark_object (ptr->contents[i]);
-       }
+       mark_vectorlike (XVECTOR (obj));
       break;
 
     case Lisp_Symbol:
@@ -5690,14 +5563,13 @@ mark_object (arg)
 
     case Lisp_Misc:
       CHECK_ALLOCATED_AND_LIVE (live_misc_p);
-      if (XMARKER (obj)->gcmarkbit)
+      if (XMISCANY (obj)->gcmarkbit)
        break;
-      XMARKER (obj)->gcmarkbit = 1;
+      XMISCANY (obj)->gcmarkbit = 1;
 
       switch (XMISCTYPE (obj))
        {
        case Lisp_Misc_Buffer_Local_Value:
-       case Lisp_Misc_Some_Buffer_Local_Value:
          {
            register struct Lisp_Buffer_Local_Value *ptr
              = XBUFFER_LOCAL_VALUE (obj);
@@ -5834,6 +5706,8 @@ mark_buffer (buf)
       mark_object (tmp);
     }
 
+  /* buffer-local Lisp variables start at `undo_list',
+     tho only the ones from `name' on are GC'd normally.  */
   for (ptr = &buffer->name;
        (char *)ptr < (char *)buffer + sizeof (struct buffer);
        ptr++)
@@ -5847,6 +5721,24 @@ mark_buffer (buf)
     }
 }
 
+/* Mark the Lisp pointers in the terminal objects.
+   Called by the Fgarbage_collector.  */
+
+static void
+mark_terminals (void)
+{
+  struct terminal *t;
+  for (t = terminal_list; t; t = t->next_terminal)
+    {
+      eassert (t->name != NULL);
+#ifdef HAVE_WINDOW_SYSTEM
+      mark_image_cache (t->image_cache);
+#endif /* HAVE_WINDOW_SYSTEM */
+      mark_vectorlike ((struct Lisp_Vector *)t);
+    }
+}
+
+
 
 /* Value is non-zero if OBJ will survive the current GC because it's
    either marked or does not need to be marked to survive.  */
@@ -5857,7 +5749,7 @@ survives_gc_p (obj)
 {
   int survives_p;
 
-  switch (XGCTYPE (obj))
+  switch (XTYPE (obj))
     {
     case Lisp_Int:
       survives_p = 1;
@@ -5868,7 +5760,7 @@ survives_gc_p (obj)
       break;
 
     case Lisp_Misc:
-      survives_p = XMARKER (obj)->gcmarkbit;
+      survives_p = XMISCANY (obj)->gcmarkbit;
       break;
 
     case Lisp_String:
@@ -5876,7 +5768,7 @@ survives_gc_p (obj)
       break;
 
     case Lisp_Vectorlike:
-      survives_p = GC_SUBRP (obj) || VECTOR_MARKED_P (XVECTOR (obj));
+      survives_p = SUBRP (obj) || VECTOR_MARKED_P (XVECTOR (obj));
       break;
 
     case Lisp_Cons:
@@ -5922,23 +5814,51 @@ gc_sweep ()
 
     for (cblk = cons_block; cblk; cblk = *cprev)
       {
-       register int i;
+       register int i = 0;
        int this_free = 0;
-       for (i = 0; i < lim; i++)
-         if (!CONS_MARKED_P (&cblk->conses[i]))
-           {
-             this_free++;
-             cblk->conses[i].u.chain = cons_free_list;
-             cons_free_list = &cblk->conses[i];
+       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[i]);
-           }
+                     }
+                   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
@@ -6137,9 +6057,9 @@ gc_sweep ()
 
        for (i = 0; i < lim; i++)
          {
-           if (!mblk->markers[i].u_marker.gcmarkbit)
+           if (!mblk->markers[i].u_any.gcmarkbit)
              {
-               if (mblk->markers[i].u_marker.type == Lisp_Misc_Marker)
+               if (mblk->markers[i].u_any.type == Lisp_Misc_Marker)
                  unchain_marker (&mblk->markers[i].u_marker);
                /* Set the type of the freed object to Lisp_Misc_Free.
                   We could leave the type alone, since nobody checks it,
@@ -6152,7 +6072,7 @@ gc_sweep ()
            else
              {
                num_used++;
-               mblk->markers[i].u_marker.gcmarkbit = 0;
+               mblk->markers[i].u_any.gcmarkbit = 0;
              }
          }
        lim = MARKER_BLOCK_SIZE;
@@ -6284,13 +6204,14 @@ Frames, windows, buffers, and subprocesses count as vectors
 }
 
 int suppress_checking;
+
 void
 die (msg, file, line)
      const char *msg;
      const char *file;
      int line;
 {
-  fprintf (stderr, "\r\nEmacs fatal error: %s:%d: %s\r\n",
+  fprintf (stderr, "\r\n%s:%d: Emacs fatal error: %s\r\n",
           file, line, msg);
   abort ();
 }
@@ -6328,6 +6249,7 @@ init_alloc_once ()
   init_marker ();
   init_float ();
   init_intervals ();
+  init_weak_hash_tables ();
 
 #ifdef REL_ALLOC
   malloc_hysteresis = 32;