diff src/alloc.c @ 400:a86b2b5e0111 r21-2-30

Import from CVS: tag r21-2-30
author cvs
date Mon, 13 Aug 2007 11:14:34 +0200
parents 74fd4e045ea6
children 2f8bb876ab1d
line wrap: on
line diff
--- a/src/alloc.c	Mon Aug 13 11:13:33 2007 +0200
+++ b/src/alloc.c	Mon Aug 13 11:14:34 2007 +0200
@@ -383,17 +383,14 @@
 {
   struct lcrecord_header *lcheader;
 
-#ifdef ERROR_CHECK_TYPECHECK
-  if (implementation->static_size == 0)
-    assert (implementation->size_in_bytes_method);
-  else
-    assert (implementation->static_size == size);
-
-  assert (! implementation->basic_p);
-
-  if (implementation->hash == NULL)
-    assert (implementation->equal == NULL);
-#endif
+  type_checking_assert
+    ((implementation->static_size == 0 ?
+      implementation->size_in_bytes_method != NULL :
+      implementation->static_size == size)
+     &&
+     (! implementation->basic_p)
+     &&
+     (! (implementation->hash == NULL && implementation->equal != NULL)));
 
   lcheader = (struct lcrecord_header *) allocate_lisp_storage (size);
   set_lheader_implementation (&(lcheader->lheader), implementation);
@@ -455,24 +452,12 @@
 
   for (header = all_lcrecords; header; header = header->next)
     {
-      if (LHEADER_IMPLEMENTATION(&header->lheader)->finalizer &&
+      if (LHEADER_IMPLEMENTATION (&header->lheader)->finalizer &&
 	  !header->free)
-	((LHEADER_IMPLEMENTATION(&header->lheader)->finalizer)
-	 (header, 1));
+	LHEADER_IMPLEMENTATION (&header->lheader)->finalizer (header, 1);
     }
 }
 
-/* Semi-kludge -- lrecord_symbol_value_forward objects get stuck
-   in const space and you get SEGV's if you attempt to mark them.
-   This sits in lheader->implementation->marker. */
-
-Lisp_Object
-this_one_is_unmarkable (Lisp_Object obj)
-{
-  abort ();
-  return Qnil;
-}
-
 
 /************************************************************************/
 /*			  Debugger support				*/
@@ -491,42 +476,6 @@
 unsigned char dbg_USE_UNION_TYPE = 0;
 #endif
 
-unsigned char Lisp_Type_Int = 100;
-unsigned char Lisp_Type_Cons = 101;
-unsigned char Lisp_Type_String = 102;
-unsigned char Lisp_Type_Vector = 103;
-unsigned char Lisp_Type_Symbol = 104;
-
-#ifndef MULE
-unsigned char lrecord_char_table_entry;
-unsigned char lrecord_charset;
-#ifndef FILE_CODING
-unsigned char lrecord_coding_system;
-#endif
-#endif
-
-#if !((defined HAVE_X_WINDOWS) && \
-      (defined (HAVE_MENUBARS)   || \
-       defined (HAVE_SCROLLBARS) || \
-       defined (HAVE_DIALOGS)    || \
-       defined (HAVE_TOOLBARS)   || \
-       defined (HAVE_WIDGETS)))
-unsigned char lrecord_popup_data;
-#endif
-
-#ifndef HAVE_TOOLBARS
-unsigned char lrecord_toolbar_button;
-#endif
-
-#ifndef TOOLTALK
-unsigned char lrecord_tooltalk_message;
-unsigned char lrecord_tooltalk_pattern;
-#endif
-
-#ifndef HAVE_DATABASE
-unsigned char lrecord_database;
-#endif
-
 unsigned char dbg_valbits = VALBITS;
 unsigned char dbg_gctypebits = GCTYPEBITS;
 
@@ -2272,22 +2221,23 @@
       struct free_lcrecord_header *free_header =
 	(struct free_lcrecord_header *) lheader;
 
-#ifdef ERROR_CHECK_GC
-      const struct lrecord_implementation *implementation
-	= LHEADER_IMPLEMENTATION(lheader);
-
-      /* There should be no other pointers to the free list. */
-      assert (!MARKED_RECORD_HEADER_P (lheader));
-      /* Only lcrecords should be here. */
-      assert (!implementation->basic_p);
-      /* Only free lcrecords should be here. */
-      assert (free_header->lcheader.free);
-      /* The type of the lcrecord must be right. */
-      assert (implementation == list->implementation);
-      /* So must the size. */
-      assert (implementation->static_size == 0
-	      || implementation->static_size == list->size);
-#endif /* ERROR_CHECK_GC */
+      gc_checking_assert
+	(/* There should be no other pointers to the free list. */
+	 ! MARKED_RECORD_HEADER_P (lheader)
+	 &&
+	 /* Only lcrecords should be here. */
+	 ! LHEADER_IMPLEMENTATION (lheader)->basic_p
+	 &&
+	 /* Only free lcrecords should be here. */
+	 free_header->lcheader.free
+	 &&
+	 /* The type of the lcrecord must be right. */
+	 LHEADER_IMPLEMENTATION (lheader) == list->implementation
+	 &&
+	 /* So must the size. */
+	 (LHEADER_IMPLEMENTATION (lheader)->static_size == 0 ||
+	  LHEADER_IMPLEMENTATION (lheader)->static_size == list->size)
+	 );
 
       MARK_RECORD_HEADER (lheader);
       chain = free_header->chain;
@@ -2325,23 +2275,21 @@
 	(struct free_lcrecord_header *) XPNTR (val);
 
 #ifdef ERROR_CHECK_GC
-      struct lrecord_header *lheader =
-	(struct lrecord_header *) free_header;
-      const struct lrecord_implementation *implementation
-	= LHEADER_IMPLEMENTATION (lheader);
+      struct lrecord_header *lheader = &free_header->lcheader.lheader;
 
       /* There should be no other pointers to the free list. */
-      assert (!MARKED_RECORD_HEADER_P (lheader));
+      assert (! MARKED_RECORD_HEADER_P (lheader));
       /* Only lcrecords should be here. */
-      assert (!implementation->basic_p);
+      assert (! LHEADER_IMPLEMENTATION (lheader)->basic_p);
       /* Only free lcrecords should be here. */
       assert (free_header->lcheader.free);
       /* The type of the lcrecord must be right. */
-      assert (implementation == list->implementation);
+      assert (LHEADER_IMPLEMENTATION (lheader) == list->implementation);
       /* So must the size. */
-      assert (implementation->static_size == 0
-	      || implementation->static_size == list->size);
+      assert (LHEADER_IMPLEMENTATION (lheader)->static_size == 0 ||
+	      LHEADER_IMPLEMENTATION (lheader)->static_size == list->size);
 #endif /* ERROR_CHECK_GC */
+
       list->free = free_header->chain;
       free_header->lcheader.free = 0;
       return val;
@@ -2362,19 +2310,16 @@
   struct lcrecord_list *list = XLCRECORD_LIST (lcrecord_list);
   struct free_lcrecord_header *free_header =
     (struct free_lcrecord_header *) XPNTR (lcrecord);
-  struct lrecord_header *lheader =
-    (struct lrecord_header *) free_header;
+  struct lrecord_header *lheader = &free_header->lcheader.lheader;
   const struct lrecord_implementation *implementation
     = LHEADER_IMPLEMENTATION (lheader);
 
-#ifdef ERROR_CHECK_GC
   /* Make sure the size is correct.  This will catch, for example,
      putting a window configuration on the wrong free list. */
-  if (implementation->size_in_bytes_method)
-    assert (implementation->size_in_bytes_method (lheader) == list->size);
-  else
-    assert (implementation->static_size == list->size);
-#endif /* ERROR_CHECK_GC */
+  gc_checking_assert ((implementation->size_in_bytes_method ?
+		       implementation->size_in_bytes_method (lheader) :
+		       implementation->static_size)
+		      == list->size);
 
   if (implementation->finalizer)
     implementation->finalizer (lheader, 0);
@@ -2398,7 +2343,6 @@
   return obj;
 }
 
-
 
 /************************************************************************/
 /*			   Garbage Collection				*/
@@ -2407,8 +2351,16 @@
 /* This will be used more extensively In The Future */
 static int last_lrecord_type_index_assigned;
 
-const struct lrecord_implementation *lrecord_implementations_table[128];
-#define max_lrecord_type (countof (lrecord_implementations_table) - 1)
+/* All the built-in lisp object types are enumerated in `enum lrecord_type'.
+   Additional ones may be defined by a module (none yet).  We leave some
+   room in `lrecord_implementations_table' for such new lisp object types. */
+#define MODULE_DEFINABLE_TYPE_COUNT 32
+const struct lrecord_implementation *lrecord_implementations_table[lrecord_type_count + MODULE_DEFINABLE_TYPE_COUNT];
+
+/* Object marker functions are in the lrecord_implementation structure.
+   But copying them to a parallel array is much more cache-friendly.
+   This hack speeds up (garbage-collect) by about 5%. */
+Lisp_Object (*lrecord_markers[countof (lrecord_implementations_table)]) (Lisp_Object);
 
 struct gcpro *gcprolist;
 
@@ -2525,6 +2477,19 @@
   pdump_wirevec_list[pdump_wireidx_list++] = varaddress;
 }
 
+#ifdef ERROR_CHECK_GC
+#define GC_CHECK_LHEADER_INVARIANTS(lheader) do {		\
+  struct lrecord_header * GCLI_lh = (lheader);			\
+  assert (GCLI_lh != 0);					\
+  assert (GCLI_lh->type <= last_lrecord_type_index_assigned);	\
+  assert (! C_READONLY_RECORD_HEADER_P (GCLI_lh) ||		\
+	  (MARKED_RECORD_HEADER_P (GCLI_lh) &&			\
+	   LISP_READONLY_RECORD_HEADER_P (GCLI_lh)));		\
+} while (0)
+#else
+#define GC_CHECK_LHEADER_INVARIANTS(lheader)
+#endif
+
 
 /* Mark reference to a Lisp_Object.  If the object referred to has not been
    seen yet, recursively mark all the references contained in it. */
@@ -2534,9 +2499,6 @@
 {
  tail_recurse:
 
-#ifdef ERROR_CHECK_GC
-  assert (! (EQ (obj, Qnull_pointer)));
-#endif
   /* Checks we used to perform */
   /* if (EQ (obj, Qnull_pointer)) return; */
   /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */
@@ -2545,25 +2507,21 @@
   if (XTYPE (obj) == Lisp_Type_Record)
     {
       struct lrecord_header *lheader = XRECORD_LHEADER (obj);
-#if defined (ERROR_CHECK_GC)
-      assert (lheader->type <= last_lrecord_type_index_assigned);
-#endif
-      if (C_READONLY_RECORD_HEADER_P (lheader))
-	return;
-
-      if (! MARKED_RECORD_HEADER_P (lheader) &&
-	  ! UNMARKABLE_RECORD_HEADER_P (lheader))
+
+      GC_CHECK_LHEADER_INVARIANTS (lheader);
+
+      gc_checking_assert (LHEADER_IMPLEMENTATION (lheader)->basic_p ||
+			  ! ((struct lcrecord_header *) lheader)->free);
+
+      /* All c_readonly objects have their mark bit set,
+	 so that we only need to check the mark bit here. */
+      if (! MARKED_RECORD_HEADER_P (lheader))
 	{
-	  const struct lrecord_implementation *implementation =
-	    LHEADER_IMPLEMENTATION (lheader);
 	  MARK_RECORD_HEADER (lheader);
-#ifdef ERROR_CHECK_GC
-	  if (!implementation->basic_p)
-	    assert (! ((struct lcrecord_header *) lheader)->free);
-#endif
-	  if (implementation->marker)
+
+	  if (RECORD_MARKER (lheader))
 	    {
-	      obj = implementation->marker (obj);
+	      obj = RECORD_MARKER (lheader) (obj);
 	      if (!NILP (obj)) goto tail_recurse;
 	    }
 	}
@@ -2603,24 +2561,6 @@
 /* static int gc_count_total_records_used, gc_count_records_total_size; */
 
 
-int
-lrecord_type_index (const struct lrecord_implementation *implementation)
-{
-  int type_index = *(implementation->lrecord_type_index);
-  /* Have to do this circuitous validation test because of problems
-     dumping out initialized variables (ie can't set xxx_type_index to -1
-     because that would make xxx_type_index read-only in a dumped emacs. */
-  if (type_index < 0 || type_index > max_lrecord_type
-      || lrecord_implementations_table[type_index] != implementation)
-    {
-      assert (last_lrecord_type_index_assigned < max_lrecord_type);
-      type_index = ++last_lrecord_type_index_assigned;
-      lrecord_implementations_table[type_index] = implementation;
-      *(implementation->lrecord_type_index) = type_index;
-    }
-  return type_index;
-}
-
 /* stats on lcrecords in use - kinda kludgy */
 
 static struct
@@ -2635,21 +2575,21 @@
 static void
 tick_lcrecord_stats (const struct lrecord_header *h, int free_p)
 {
-  const struct lrecord_implementation *implementation =
-    LHEADER_IMPLEMENTATION (h);
-  int type_index = lrecord_type_index (implementation);
+  unsigned int type_index = h->type;
 
   if (((struct lcrecord_header *) h)->free)
     {
-      assert (!free_p);
+      gc_checking_assert (!free_p);
       lcrecord_stats[type_index].instances_on_free_list++;
     }
   else
     {
-      size_t sz = (implementation->size_in_bytes_method
-		   ? implementation->size_in_bytes_method (h)
-		   : implementation->static_size);
-
+      const struct lrecord_implementation *implementation =
+	LHEADER_IMPLEMENTATION (h);
+
+      size_t sz = (implementation->size_in_bytes_method ?
+		   implementation->size_in_bytes_method (h) :
+		   implementation->static_size);
       if (free_p)
 	{
 	  lcrecord_stats[type_index].instances_freed++;
@@ -2687,9 +2627,10 @@
   for (header = *prev; header; header = header->next)
     {
       struct lrecord_header *h = &(header->lheader);
-      if (!C_READONLY_RECORD_HEADER_P(h)
-	  && !MARKED_RECORD_HEADER_P (h)
-	  && ! (header->free))
+
+      GC_CHECK_LHEADER_INVARIANTS (h);
+
+      if (! MARKED_RECORD_HEADER_P (h) && ! header->free)
 	{
 	  if (LHEADER_IMPLEMENTATION (h)->finalizer)
 	    LHEADER_IMPLEMENTATION (h)->finalizer (h, 0);
@@ -2699,9 +2640,9 @@
   for (header = *prev; header; )
     {
       struct lrecord_header *h = &(header->lheader);
-      if (C_READONLY_RECORD_HEADER_P(h) || MARKED_RECORD_HEADER_P (h))
+      if (MARKED_RECORD_HEADER_P (h))
 	{
-	  if (MARKED_RECORD_HEADER_P (h))
+	  if (! C_READONLY_RECORD_HEADER_P (h))
 	    UNMARK_RECORD_HEADER (h);
 	  num_used++;
 	  /* total_size += n->implementation->size_in_bytes (h);*/
@@ -2740,9 +2681,9 @@
     {
       Lisp_Bit_Vector *v = XBIT_VECTOR (bit_vector);
       int len = v->size;
-      if (C_READONLY_RECORD_HEADER_P(&(v->lheader)) || MARKED_RECORD_P (bit_vector))
+      if (MARKED_RECORD_P (bit_vector))
 	{
-	  if (MARKED_RECORD_P (bit_vector))
+	  if (! C_READONLY_RECORD_HEADER_P(&(v->lheader)))
 	    UNMARK_RECORD_HEADER (&(v->lheader));
 	  total_size += len;
           total_storage +=
@@ -2798,7 +2739,7 @@
 	    {								\
 	      num_used++;						\
 	    }								\
-	  else if (!MARKED_RECORD_HEADER_P (&SFTB_victim->lheader))	\
+	  else if (! MARKED_RECORD_HEADER_P (&SFTB_victim->lheader))	\
 	    {								\
 	      num_free++;						\
 	      FREE_FIXED_TYPE (typename, obj_type, SFTB_victim);	\
@@ -2853,7 +2794,7 @@
 	      SFTB_empty = 0;							\
 	      num_used++;							\
 	    }									\
-	  else if (!MARKED_RECORD_HEADER_P (&SFTB_victim->lheader))		\
+	  else if (! MARKED_RECORD_HEADER_P (&SFTB_victim->lheader))		\
 	    {									\
 	      num_free++;							\
 	      FREE_FIXED_TYPE (typename, obj_type, SFTB_victim);		\
@@ -3032,12 +2973,8 @@
 void
 free_marker (Lisp_Marker *ptr)
 {
-#ifdef ERROR_CHECK_GC
   /* Perhaps this will catch freeing an already-freed marker. */
-  Lisp_Object temmy;
-  XSETMARKER (temmy, ptr);
-  assert (MARKERP (temmy));
-#endif /* ERROR_CHECK_GC */
+  gc_checking_assert (ptr->lheader.type = lrecord_type_marker);
 
 #ifndef ALLOC_NO_POOLS
   FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, Lisp_Marker, ptr);
@@ -3253,9 +3190,6 @@
 int
 marked_p (Lisp_Object obj)
 {
-#ifdef ERROR_CHECK_GC
-  assert (! (EQ (obj, Qnull_pointer)));
-#endif
   /* Checks we used to perform. */
   /* if (EQ (obj, Qnull_pointer)) return 1; */
   /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */
@@ -3264,10 +3198,10 @@
   if (XTYPE (obj) == Lisp_Type_Record)
     {
       struct lrecord_header *lheader = XRECORD_LHEADER (obj);
-#if defined (ERROR_CHECK_GC)
-      assert (lheader->type <= last_lrecord_type_index_assigned);
-#endif
-      return C_READONLY_RECORD_HEADER_P (lheader) || MARKED_RECORD_HEADER_P (lheader);
+
+      GC_CHECK_LHEADER_INVARIANTS (lheader);
+
+      return MARKED_RECORD_HEADER_P (lheader);
     }
   return 1;
 }
@@ -3345,7 +3279,9 @@
 	    {
 	      for (i=0; i<rt->count; i++)
 		{
-		  UNMARK_RECORD_HEADER ((struct lrecord_header *)(*(EMACS_INT *)p));
+		  struct lrecord_header *lh = * (struct lrecord_header **) p;
+		  if (! C_READONLY_RECORD_HEADER_P (lh))
+		    UNMARK_RECORD_HEADER (lh);
 		  p += sizeof (EMACS_INT);
 		}
 	    } else
@@ -3726,7 +3662,7 @@
           const char *name = lrecord_implementations_table[i]->name;
 	  int len = strlen (name);
 	  /* save this for the FSFmacs-compatible part of the summary */
-	  if (i == *lrecord_vector.lrecord_type_index)
+	  if (i == lrecord_vector.lrecord_type_index)
 	    gc_count_vector_total_size =
 	      lcrecord_stats[i].bytes_in_use + lcrecord_stats[i].bytes_freed;
 
@@ -4055,31 +3991,20 @@
 void
 init_alloc_once_early (void)
 {
-  int iii;
-
   reinit_alloc_once_early ();
 
-  last_lrecord_type_index_assigned = -1;
-  for (iii = 0; iii < countof (lrecord_implementations_table); iii++)
-    {
-      lrecord_implementations_table[iii] = 0;
-    }
-
-  /*
-   * All the staticly
-   * defined subr lrecords were initialized with lheader->type == 0.
-   * See subr_lheader_initializer in lisp.h.  Force type index 0 to be
-   * assigned to lrecord_subr so that those predefined indexes match
-   * reality.
-   */
-  lrecord_type_index (&lrecord_subr);
-  assert (*(lrecord_subr.lrecord_type_index) == 0);
-  /*
-   * The same is true for symbol_value_forward objects, except the
-   * type is 1.
-   */
-  lrecord_type_index (&lrecord_symbol_value_forward);
-  assert (*(lrecord_symbol_value_forward.lrecord_type_index) == 1);
+  last_lrecord_type_index_assigned = lrecord_type_count - 1;
+
+  {
+    int i;
+    for (i = 0; i < countof (lrecord_implementations_table); i++)
+      lrecord_implementations_table[i] = 0;
+  }
+
+  INIT_LRECORD_IMPLEMENTATION (cons);
+  INIT_LRECORD_IMPLEMENTATION (vector);
+  INIT_LRECORD_IMPLEMENTATION (string);
+  INIT_LRECORD_IMPLEMENTATION (lcrecord_list);
 
   staticidx = 0;
 }
@@ -5190,13 +5115,10 @@
   memcpy (lrecord_implementations_table, p, sizeof (lrecord_implementations_table));
   p += sizeof (lrecord_implementations_table);
 
-  /* Give back their numbers to the lrecord implementations */
-  for (i = 0; i < countof (lrecord_implementations_table); i++)
+  /* Reinitialize lrecord_markers from lrecord_implementations_table */
+  for (i=0; i < countof (lrecord_implementations_table); i++)
     if (lrecord_implementations_table[i])
-      {
-	*(lrecord_implementations_table[i]->lrecord_type_index) = i;
-	last_lrecord_type_index_assigned = i;
-      }
+      lrecord_markers[i] = lrecord_implementations_table[i]->marker;
 
   /* Do the relocations */
   pdump_rt_list = p;
@@ -5256,3 +5178,4 @@
 }
 
 #endif /* PDUMP */
+