diff src/alloc.c @ 207:e45d5e7c476e r20-4b2

Import from CVS: tag r20-4b2
author cvs
date Mon, 13 Aug 2007 10:03:52 +0200
parents a2f645c6b9f8
children 78478c60bfcd
line wrap: on
line diff
--- a/src/alloc.c	Mon Aug 13 10:02:48 2007 +0200
+++ b/src/alloc.c	Mon Aug 13 10:03:52 2007 +0200
@@ -62,7 +62,10 @@
 /* #define VERIFY_STRING_CHARS_INTEGRITY */
 
 /* Define this to see where all that space is going... */
+/* But the length of the printout is obnoxious, so limit it to testers */
+#ifdef DEBUG_XEMACS
 #define PURESTAT
+#endif
 
 /* Define this to use malloc/free with no freelist for all datatypes,
    the hope being that some debugging tools may help detect
@@ -486,8 +489,8 @@
   char *lim = ((char *) p) + size;
   Lisp_Object val = Qnil;
 
-  XSETCONS (val, lim);
-  if ((char *) XCONS (val) != lim)
+  XSETOBJ (val, Lisp_Type_Record, lim);
+  if ((char *) XPNTR (val) != lim)
     {
       xfree (p);
       memory_full ();
@@ -496,16 +499,6 @@
 }
 
 
-#define MARKED_RECORD_HEADER_P(lheader) \
-  (((lheader)->implementation->finalizer) == this_marks_a_marked_record)
-#define UNMARKABLE_RECORD_HEADER_P(lheader) \
-  (((lheader)->implementation->marker) == this_one_is_unmarkable)
-#define MARK_RECORD_HEADER(lheader) \
-  do { (((lheader)->implementation)++); } while (0)
-#define UNMARK_RECORD_HEADER(lheader) \
-  do { (((lheader)->implementation)--); } while (0)
-
-
 /* lrecords are chained together through their "next.v" field.
  * After doing the mark phase, the GC will walk this linked
  *  list and free any record which hasn't been marked
@@ -991,6 +984,44 @@
 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 20000 */
 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 2000
 
+#ifdef LRECORD_CONS
+static Lisp_Object mark_cons (Lisp_Object, void (*) (Lisp_Object));
+static int cons_equal(Lisp_Object, Lisp_Object, int);
+extern void print_cons (Lisp_Object, Lisp_Object, int);
+DEFINE_BASIC_LRECORD_IMPLEMENTATION ("cons", cons,
+				     mark_cons, print_cons, 0,
+				     cons_equal, 
+				     /*
+				      * No `hash' method needed.
+				      * internal_hash knows how to
+				      * handle conses.
+				      */
+				     0,
+				     struct Lisp_Cons);
+static Lisp_Object
+mark_cons (Lisp_Object obj, void (*markobj) (Lisp_Object))
+{
+  if (NILP (XCDR (obj)))
+    return XCAR (obj);
+  else
+    (markobj) (XCAR (obj));
+  return XCDR (obj);
+}
+
+static int
+cons_equal (Lisp_Object ob1, Lisp_Object ob2, int depth)
+{
+  while (internal_equal (XCAR (ob1), XCAR (ob2), depth + 1))
+    {
+      ob1 = XCDR(ob1);
+      ob2 = XCDR(ob2);
+      if (! CONSP (ob1) || ! CONSP (ob2))
+	return internal_equal (ob1, ob2, depth + 1);
+    }
+  return 0;
+}
+#endif /* LRECORD_CONS */
+
 DEFUN ("cons", Fcons, 2, 2, 0, /*
 Create a new cons, give it CAR and CDR as components, and return it.
 */
@@ -1001,9 +1032,12 @@
   struct Lisp_Cons *c;
 
   ALLOCATE_FIXED_TYPE (cons, struct Lisp_Cons, c);
+#ifdef LRECORD_CONS
+  set_lheader_implementation (&(c->lheader), lrecord_cons);
+#endif
   XSETCONS (val, c);
-  XCAR (val) = car;
-  XCDR (val) = cdr;
+  c->car = car;
+  c->cdr = cdr;
   return val;
 }
 
@@ -1017,6 +1051,9 @@
   struct Lisp_Cons *c;
 
   NOSEEUM_ALLOCATE_FIXED_TYPE (cons, struct Lisp_Cons, c);
+#ifdef LRECORD_CONS
+  set_lheader_implementation (&(c->lheader), lrecord_cons);
+#endif
   XSETCONS (val, c);
   XCAR (val) = car;
   XCDR (val) = cdr;
@@ -1136,6 +1173,77 @@
 /*                         Vector allocation                          */
 /**********************************************************************/
 
+#ifdef LRECORD_VECTOR
+static Lisp_Object mark_vector (Lisp_Object, void (*) (Lisp_Object));
+static unsigned int size_vector (CONST void *);
+static int vector_equal(Lisp_Object, Lisp_Object, int);
+extern void print_vector (Lisp_Object, Lisp_Object, int);
+DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("vector", vector,
+				       mark_vector, print_vector, 0,
+				       vector_equal,
+				       /*
+				        * No `hash' method needed for
+				        * vectors.  internal_hash
+				        * knows how to handle vectors.
+				        */
+				       0,
+				       size_vector, struct Lisp_Vector);
+static Lisp_Object
+mark_vector (Lisp_Object obj, void (*markobj) (Lisp_Object))
+{
+  struct Lisp_Vector *ptr = XVECTOR (obj);
+  int len = vector_length (ptr);
+  int i;
+
+  for (i = 0; i < len - 1; i++)
+    (markobj) (ptr->contents[i]);
+  return (len > 0) ? ptr->contents[len - 1] : Qnil;
+}
+
+static unsigned int
+size_vector (CONST void *lheader)
+{
+  struct Lisp_Vector *p = lheader;
+  /*
+   * -1 because struct Lisp_Vector includes 1 slot
+   */
+  return sizeof (struct Lisp_Vector) +
+    ((p->size - 1) * sizeof (Lisp_Object)) ;
+}
+
+static int
+vector_equal (Lisp_Object o1, Lisp_Object o2, int depth)
+{
+  int indice;
+  int len = XVECTOR_LENGTH (o1);
+  if (len != XVECTOR_LENGTH (o2))
+    return 0;
+  for (indice = 0; indice < len; indice++)
+    {
+      if (!internal_equal (XVECTOR_DATA (o1) [indice],
+			   XVECTOR_DATA (o2) [indice],
+			   depth + 1))
+	return 0;
+    }
+  return 1;
+}
+
+/* #### should allocate `small' vectors from a frob-block */
+static struct Lisp_Vector *
+make_vector_internal (EMACS_INT sizei)
+{
+  EMACS_INT sizem = (sizeof (struct Lisp_Vector)
+               /* -1 because struct Lisp_Vector includes 1 slot */
+               + (sizei - 1) * sizeof (Lisp_Object)
+               );
+  struct Lisp_Vector *p = alloc_lcrecord (sizem, lrecord_vector);
+
+  p->size = sizei;
+  return p;
+}
+
+#else /* ! LRECORD_VECTOR */
+
 static Lisp_Object all_vectors;
 
 /* #### should allocate `small' vectors from a frob-block */
@@ -1148,9 +1256,6 @@
                + (sizei - 1 + 1) * sizeof (Lisp_Object)
                );
   struct Lisp_Vector *p = (struct Lisp_Vector *) allocate_lisp_storage (sizem);
-#ifdef LRECORD_VECTOR
-  set_lheader_implementation (&(p->lheader), lrecord_vector);
-#endif
 
   INCREMENT_CONS_COUNTER (sizem, "vector");
 
@@ -1160,6 +1265,8 @@
   return p;
 }
 
+#endif
+
 Lisp_Object
 make_vector (EMACS_INT length, Lisp_Object init)
 {
@@ -1794,6 +1901,46 @@
 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 10000 */
 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 1000
 
+#ifdef LRECORD_STRING
+static Lisp_Object mark_string (Lisp_Object, void (*) (Lisp_Object));
+static int string_equal (Lisp_Object, Lisp_Object, int);
+extern void print_string (Lisp_Object, Lisp_Object, int);
+DEFINE_BASIC_LRECORD_IMPLEMENTATION ("string", string,
+				     mark_string, print_string,
+				     /*
+				      * No `finalize', or `hash' methods.
+				      * internal_hash already knows how
+				      * to hash strings and finalization
+				      * is done with the
+				      * ADDITIONAL_FREE_string macro,
+				      * which is the standard way to do
+				      * finalization when using
+				      * SWEEP_FIXED_TYPE_BLOCK().
+				      */
+				     0, string_equal, 0,
+				     struct Lisp_String);
+static Lisp_Object
+mark_string (Lisp_Object obj, void (*markobj) (Lisp_Object))
+{
+  struct Lisp_String *ptr = XSTRING (obj);
+
+  if (GC_CONSP (ptr->plist) && GC_EXTENT_INFOP (XCAR (ptr->plist)))
+    flush_cached_extent_info (XCAR (ptr->plist));
+  return ptr->plist;
+}
+
+static int
+string_equal (Lisp_Object o1, Lisp_Object o2, int depth)
+{
+  Bytecount len = XSTRING_LENGTH (o1);
+  if (len != XSTRING_LENGTH (o2))
+    return 0;
+  if (memcmp (XSTRING_DATA (o1), XSTRING_DATA (o2), len))
+    return 0;
+  return 1;
+}
+#endif /* LRECORD_STRING */
+
 /* String blocks contain this many useful bytes. */
 #define STRING_CHARS_BLOCK_SIZE \
   (8192 - MALLOC_OVERHEAD - ((2 * sizeof (struct string_chars_block *)) \
@@ -1905,6 +2052,9 @@
 
   /* Allocate the string header */
   ALLOCATE_FIXED_TYPE (string, struct Lisp_String, s);
+#ifdef LRECORD_STRING
+  set_lheader_implementation (&(s->lheader), lrecord_string);
+#endif
 
   s_chars = allocate_string_chars_struct (s, fullsize);
 
@@ -2357,6 +2507,9 @@
     return make_string (data, length);
 
   s = (struct Lisp_String *) (PUREBEG + pureptr);
+#ifdef LRECORD_STRING
+  set_lheader_implementation (&(s->lheader), lrecord_string);
+#endif
   set_string_length (s, length);
   if (no_need_to_copy_data)
     {
@@ -2404,16 +2557,21 @@
 pure_cons (Lisp_Object car, Lisp_Object cdr)
 {
   Lisp_Object new;
+  struct Lisp_Cons *c;
 
   if (!check_purespace (sizeof (struct Lisp_Cons)))
     return Fcons (Fpurecopy (car), Fpurecopy (cdr));
 
-  XSETCONS (new, PUREBEG + pureptr);
+  c = (struct Lisp_Cons *) (PUREBEG + pureptr);
+#ifdef LRECORD_CONS
+  set_lheader_implementation (&(c->lheader), lrecord_cons);
+#endif
   pureptr += sizeof (struct Lisp_Cons);
   bump_purestat (&purestat_cons, sizeof (struct Lisp_Cons));
 
-  XCAR (new) = Fpurecopy (car);
-  XCDR (new) = Fpurecopy (cdr);
+  c->car = Fpurecopy (car);
+  c->cdr = Fpurecopy (cdr);
+  XSETCONS (new, c);
   return new;
 }
 
@@ -2482,6 +2640,7 @@
 make_pure_vector (EMACS_INT len, Lisp_Object init)
 {
   Lisp_Object new;
+  struct Lisp_Vector *v;
   EMACS_INT size = (sizeof (struct Lisp_Vector)
               + (len - 1) * sizeof (Lisp_Object));
 
@@ -2490,15 +2649,19 @@
   if (!check_purespace (size))
     return make_vector (len, init);
 
-  XSETVECTOR (new, PUREBEG + pureptr);
+  v = (struct Lisp_Vector *) (PUREBEG + pureptr);
+#ifdef LRECORD_VECTOR
+  set_lheader_implementation (&(v->header.lheader), lrecord_vector);
+#endif
   pureptr += size;
   bump_purestat (&purestat_vector_all, size);
 
-  XVECTOR_LENGTH (new) = len;
+  v->size = len;
 
   for (size = 0; size < len; size++)
-    XVECTOR_DATA (new)[size] = init;
-
+    v->contents[size] = init;
+
+  XSETVECTOR (new, v); 
   return new;
 }
 
@@ -2532,19 +2695,25 @@
     return obj;
 
   if (!POINTER_TYPE_P (XTYPE (obj))
-      || PURIFIED (XPNTR (obj)))
+      || PURIFIED (XPNTR (obj))
+      /* happens when bootstrapping Qnil */
+      || EQ (obj, Qnull_pointer))
     return obj;
 
   switch (XTYPE (obj))
     {
+#ifndef LRECORD_CONS
     case Lisp_Type_Cons:
       return pure_cons (XCAR (obj), XCDR (obj));
-
+#endif
+
+#ifndef LRECORD_STRING
     case Lisp_Type_String:
       return make_pure_string (XSTRING_DATA (obj),
 			       XSTRING_LENGTH (obj),
 			       XSTRING (obj)->plist,
                                0);
+#endif /* ! LRECORD_STRING */
 
 #ifndef LRECORD_VECTOR
     case Lisp_Type_Vector:
@@ -2573,6 +2742,29 @@
 	    n->maxdepth = o->maxdepth;
             return new;
           }
+#ifdef LRECORD_CONS
+      else if (CONSP (obj))
+	return pure_cons (XCAR (obj), XCDR (obj));
+#endif /* LRECORD_CONS */
+#ifdef LRECORD_VECTOR
+      else if (VECTORP (obj))
+	{
+	  struct Lisp_Vector *o = XVECTOR (obj);
+	  Lisp_Object new = make_pure_vector (vector_length (o), Qnil);
+	  for (i = 0; i < vector_length (o); i++)
+	    XVECTOR_DATA (new)[i] = Fpurecopy (o->contents[i]);
+	  return new;
+	}
+#endif /* LRECORD_VECTOR */
+#ifdef LRECORD_STRING
+      else if (STRINGP (obj))
+	{
+	  return make_pure_string (XSTRING_DATA (obj),
+				   XSTRING_LENGTH (obj),
+				   XSTRING (obj)->plist,
+				   0);
+	}
+#endif /* LRECORD_STRING */
 #ifdef LISP_FLOAT_TYPE
         else if (FLOATP (obj))
           return make_pure_float (float_data (XFLOAT (obj)));
@@ -2776,12 +2968,15 @@
 {
  tail_recurse:
 
+  if (EQ (obj, Qnull_pointer))
+    return;
   if (!POINTER_TYPE_P (XGCTYPE (obj)))
     return;
   if (PURIFIED (XPNTR (obj)))
     return;
   switch (XGCTYPE (obj))
     {
+#ifndef LRECORD_CONS
     case Lisp_Type_Cons:
       {
 	struct Lisp_Cons *ptr = XCONS (obj);
@@ -2800,6 +2995,7 @@
 	  }
 	goto tail_recurse;
       }
+#endif
 
     case Lisp_Type_Record:
     /* case Lisp_Symbol_Value_Magic: */
@@ -2825,6 +3021,7 @@
       }
       break;
 
+#ifndef LRECORD_STRING
     case Lisp_Type_String:
       {
 	struct Lisp_String *ptr = XSTRING (obj);
@@ -2840,6 +3037,7 @@
 	  }
       }
       break;
+#endif /* ! LRECORD_STRING */
 
 #ifndef LRECORD_VECTOR
     case Lisp_Type_Vector:
@@ -2873,15 +3071,13 @@
 	    mark_object (sym->value);
 	    mark_object (sym->function);
 	    {
-	      /*  Open-code mark_string */
-	      /*  symbol->name is a struct Lisp_String *, not a Lisp_Object */
-	      struct Lisp_String *pname = sym->name;
-	      if (!PURIFIED (pname)
-		  && !XMARKBIT (pname->plist))
-		{
-		  XMARK (pname->plist);
-		  mark_object (pname->plist);
-		}
+	      /*
+	       * symbol->name is a struct Lisp_String *, not a
+	       * Lisp_Object.  Fix it up and pass to mark_object.
+	       */
+	      Lisp_Object symname;
+	      XSETSTRING(symname, sym->name);
+	      mark_object(symname);
 	    }
 	    if (!symbol_next (sym))
 	      {
@@ -2936,6 +3132,27 @@
 }
 #endif /* unused */
 
+static int
+pure_string_sizeof(Lisp_Object obj)
+{
+  struct Lisp_String *ptr = XSTRING (obj);
+  int size = string_length (ptr);
+
+  if (string_data (ptr) !=
+      (unsigned char *) ptr + sizeof (struct Lisp_String))
+    {
+      /* string-data not allocated contiguously.
+	 Probably (better be!!) a pointer constant "C" data. */
+      size = sizeof (struct Lisp_String);
+    }
+  else
+    {
+      size = sizeof (struct Lisp_String) + size + 1;
+      size = ALIGN_SIZE (size, sizeof (Lisp_Object));
+    }
+  return size;
+}
+
 /* recurse arg isn't actually used */
 static int
 pure_sizeof (Lisp_Object obj /*, int recurse */)
@@ -2953,26 +3170,14 @@
 
   switch (XTYPE (obj))
     {
+
+#ifndef LRECORD_STRING
     case Lisp_Type_String:
       {
-	struct Lisp_String *ptr = XSTRING (obj);
-        int size = string_length (ptr);
-
-        if (string_data (ptr) !=
-	    (unsigned char *) ptr + sizeof (struct Lisp_String))
-	  {
-	    /* string-data not allocated contiguously.
-	       Probably (better be!!) a pointer constant "C" data. */
-	    size = sizeof (struct Lisp_String);
-	  }
-        else
-	  {
-	    size = sizeof (struct Lisp_String) + size + 1;
-	    size = ALIGN_SIZE (size, sizeof (Lisp_Object));
-	  }
-        total += size;
+	total += pure_string_sizeof (obj);
       }
       break;
+#endif /* ! LRECORD_STRING */
 
 #ifndef LRECORD_VECTOR
     case Lisp_Type_Vector:
@@ -2998,7 +3203,7 @@
 #endif /* unused */
       }
       break;
-#endif /* !LRECORD_SYMBOL */
+#endif /* !LRECORD_VECTOR */
 
     case Lisp_Type_Record:
       {
@@ -3006,6 +3211,11 @@
 	CONST struct lrecord_implementation *implementation
 	  = lheader->implementation;
 
+#ifdef LRECORD_STRING
+	if (STRINGP (obj))
+	  total += pure_string_sizeof (obj);
+	else
+#endif
         if (implementation->size_in_bytes_method)
           total += ((implementation->size_in_bytes_method) (lheader));
 	else
@@ -3030,6 +3240,7 @@
       }
       break;
 
+#ifndef LRECORD_CONS
     case Lisp_Type_Cons:
       {
         struct Lisp_Cons *ptr = XCONS (obj);
@@ -3051,6 +3262,7 @@
 #endif /* unused */
       }
       break;
+#endif
 
       /* Others can't be purified */
     default:
@@ -3065,8 +3277,10 @@
 
 /* Find all structures not marked, and free them. */
 
+#ifndef LRECORD_VECTOR
 static int gc_count_num_vector_used, gc_count_vector_total_size;
 static int gc_count_vector_storage;
+#endif
 static int gc_count_num_bit_vector_used, gc_count_bit_vector_total_size;
 static int gc_count_bit_vector_storage;
 static int gc_count_num_short_string_in_use;
@@ -3213,6 +3427,8 @@
   /* *total = total_size; */
 }
 
+#ifndef LRECORD_VECTOR
+
 static void
 sweep_vectors_1 (Lisp_Object *prev,
                  int *used, int *total, int *storage)
@@ -3251,6 +3467,8 @@
   *storage = total_storage;
 }
 
+#endif /* ! LRECORD_VECTOR */
+
 static void
 sweep_bit_vectors_1 (Lisp_Object *prev,
 		     int *used, int *total, int *storage)
@@ -3422,8 +3640,13 @@
 static void
 sweep_conses (void)
 {
-#define MARKED_cons_P(ptr) XMARKBIT ((ptr)->car)
-#define UNMARK_cons(ptr) do { XUNMARK ((ptr)->car); } while (0)
+#ifndef LRECORD_CONS
+# define MARKED_cons_P(ptr) XMARKBIT ((ptr)->car)
+# define UNMARK_cons(ptr) do { XUNMARK ((ptr)->car); } while (0)
+#else /* LRECORD_CONS */
+# define MARKED_cons_P(ptr) MARKED_RECORD_HEADER_P (&((ptr)->lheader))
+# define UNMARK_cons(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
+#endif /* LRECORD_CONS */
 #define ADDITIONAL_FREE_cons(ptr)
 
   SWEEP_FIXED_TYPE_BLOCK (cons, struct Lisp_Cons);
@@ -3677,7 +3900,11 @@
             abort ();
 
           /* Just skip it if it isn't marked.  */
+#ifdef LRECORD_STRING
+	  if (! MARKED_RECORD_HEADER_P (&(string->lheader)))
+#else
           if (!XMARKBIT (string->plist))
+#endif
             {
               from_pos += fullsize;
               continue;
@@ -3758,8 +3985,30 @@
   int num_small_used = 0, num_small_bytes = 0, num_bytes = 0;
   int debug = debug_string_purity;
 
-#define MARKED_string_P(ptr) XMARKBIT ((ptr)->plist)
-#define UNMARK_string(ptr)				\
+#ifdef LRECORD_STRING
+
+# define MARKED_string_P(ptr) MARKED_RECORD_HEADER_P (&((ptr)->lheader))
+# define UNMARK_string(ptr)				\
+  do { struct Lisp_String *p = (ptr);			\
+       int size = string_length (p);			\
+       UNMARK_RECORD_HEADER (&(p->lheader));		\
+       num_bytes += size;				\
+       if (!BIG_STRING_SIZE_P (size))			\
+	 { num_small_bytes += size;			\
+	   num_small_used++;				\
+	 }						\
+       if (debug) debug_string_purity_print (p);	\
+     } while (0)
+# define ADDITIONAL_FREE_string(p)				\
+  do { int size = string_length (p);				\
+       if (BIG_STRING_SIZE_P (size))				\
+	 xfree_1 (CHARS_TO_STRING_CHAR (string_data (p)));	\
+     } while (0)
+
+#else
+
+# define MARKED_string_P(ptr) XMARKBIT ((ptr)->plist)
+# define UNMARK_string(ptr)				\
   do { struct Lisp_String *p = (ptr);			\
        int size = string_length (p);			\
        XUNMARK (p->plist);				\
@@ -3770,12 +4019,14 @@
 	 }						\
        if (debug) debug_string_purity_print (p);	\
      } while (0)
-#define ADDITIONAL_FREE_string(p)				\
+# define ADDITIONAL_FREE_string(p)				\
   do { int size = string_length (p);				\
        if (BIG_STRING_SIZE_P (size))				\
 	 xfree_1 (CHARS_TO_STRING_CHAR (string_data (p)));	\
      } while (0)
 
+#endif /* ! LRECORD_STRING */
+
   SWEEP_FIXED_TYPE_BLOCK (string, struct Lisp_String);
 
   gc_count_num_short_string_in_use = num_small_used;
@@ -3788,16 +4039,21 @@
 static int
 marked_p (Lisp_Object obj)
 {
+  if (EQ (obj, Qnull_pointer)) return 1;
   if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1;
   if (PURIFIED (XPNTR (obj))) return 1;
   switch (XGCTYPE (obj))
     {
+#ifndef LRECORD_CONS
     case Lisp_Type_Cons:
       return XMARKBIT (XCAR (obj));
+#endif
     case Lisp_Type_Record:
       return MARKED_RECORD_HEADER_P (XRECORD_LHEADER (obj));
+#ifndef LRECORD_STRING
     case Lisp_Type_String:
       return XMARKBIT (XSTRING (obj)->plist);
+#endif /* ! LRECORD_STRING */
 #ifndef LRECORD_VECTOR
     case Lisp_Type_Vector:
       return XVECTOR_LENGTH (obj) < 0;
@@ -3845,10 +4101,12 @@
   /* Put all unmarked conses on free list */
   sweep_conses ();
 
+#ifndef LRECORD_VECTOR
   /* Free all unmarked vectors */
   sweep_vectors_1 (&all_vectors,
                    &gc_count_num_vector_used, &gc_count_vector_total_size,
                    &gc_count_vector_storage);
+#endif
 
   /* Free all unmarked bit vectors */
   sweep_bit_vectors_1 (&all_bit_vectors,
@@ -4232,6 +4490,9 @@
   Lisp_Object pl = Qnil;
   Lisp_Object ret[6];
   int i;
+#ifdef LRECORD_VECTOR
+  int gc_count_vector_total_size;
+#endif
 
   if (purify_flag && pure_lossage)
     {
@@ -4249,6 +4510,12 @@
           char buf [255];
           CONST char *name = lrecord_implementations_table[i]->name;
 	  int len = strlen (name);
+#ifdef LRECORD_VECTOR
+	  /* save this for the FSFmacs-compatible part of the summary */
+	  if (i == *lrecord_vector[0].lrecord_type_index)
+	    gc_count_vector_total_size =
+	      lcrecord_stats[i].bytes_in_use + lcrecord_stats[i].bytes_freed;
+#endif
           sprintf (buf, "%s-storage", name);
           pl = gc_plist_hack (buf, lcrecord_stats[i].bytes_in_use, pl);
 	  /* Okay, simple pluralization check for `symbol-value-varalias' */
@@ -4307,10 +4574,12 @@
   pl = gc_plist_hack ("compiled-functions-used",
 		      gc_count_num_compiled_function_in_use, pl);
 
+#ifndef LRECORD_VECTOR
   pl = gc_plist_hack ("vector-storage", gc_count_vector_storage, pl);
   pl = gc_plist_hack ("vectors-total-length",
                       gc_count_vector_total_size, pl);
   pl = gc_plist_hack ("vectors-used", gc_count_num_vector_used, pl);
+#endif
 
   pl = gc_plist_hack ("bit-vector-storage", gc_count_bit_vector_storage, pl);
   pl = gc_plist_hack ("bit-vectors-total-length",
@@ -4545,7 +4814,9 @@
   pureptr = 0;
   pure_lossage = 0;
   breathing_space = 0;
+#ifndef LRECORD_VECTOR
   XSETINT (all_vectors, 0); /* Qzero may not be set yet. */
+#endif
   XSETINT (all_bit_vectors, 0); /* Qzero may not be set yet. */
   XSETINT (Vgc_message, 0);
   all_lcrecords = 0;