Subject: Re: bug#6301: 23.2.50; GC may lose Lisp objects in the image cache

From: YAMAMOTO Mitsuharu <[email-masked]>
Date: Mon, 11 Oct 2010 14:47:41 +0900

>>>>> On Sat, 29 May 2010 17:37:43 +0900, YAMAMOTO Mitsuharu <[email-masked]> said:

> Currently, Fgarbage_collect calls mark_terminals after marking
> staticpro'ed objects.  Terminal objects need a special marking
> strategy with respect to image cache, but if a terminal object is
> reachable from some staticpro'ed object, then it is marked normally
> (i.e., without considering image cache).  As a result, Lisp objects in
> the image cache might be collected though they should have been
> marked.

> The simplest way to fix this would be to call mark_terminals earlier.

On second thought, the following change would be more natural.

=== modified file 'src/alloc.c'
*** src/alloc.c	2010-01-22 09:10:04 +0000
--- src/alloc.c	2010-10-10 01:56:51 +0000
*************** mark_terminals (void)
*** 5771,5783 ****
    for (t = terminal_list; t; t = t->next_terminal)
      {
        eassert (t->name != NULL);
-       if (!VECTOR_MARKED_P (t))
- 	{
  #ifdef HAVE_WINDOW_SYSTEM
! 	  mark_image_cache (t->image_cache);
  #endif /* HAVE_WINDOW_SYSTEM */
! 	  mark_vectorlike ((struct Lisp_Vector *)t);
! 	}
      }
  }
  
--- 5779,5789 ----
    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 */
!       if (!VECTOR_MARKED_P (t))
! 	mark_vectorlike ((struct Lisp_Vector *)t);
      }
  }

Also, as for stack marking, I noticed that about half of the stack
elements have Lisp_Int* tags at least on Mac OS X.  Such an element
might be either a real Lisp integer or an aligned pointer value.  We
can omit mem_find calls for them by checking the tag value early.

=== modified file 'src/alloc.c'
*** src/alloc.c	2010-01-22 09:10:04 +0000
--- src/alloc.c	2010-10-10 01:56:51 +0000
*************** static INLINE void
*** 4109,4117 ****
  mark_maybe_object (obj)
       Lisp_Object obj;
  {
!   void *po = (void *) XPNTR (obj);
!   struct mem_node *m = mem_find (po);
  
    if (m != MEM_NIL)
      {
        int mark_p = 0;
--- 4109,4125 ----
  mark_maybe_object (obj)
       Lisp_Object obj;
  {
!   void *po;
!   struct mem_node *m;
! 
!   switch (XTYPE (obj))
!     {
!     case_Lisp_Int:
!       return;
!     }
  
+   po = (void *) XPNTR (obj);
+   m = mem_find (po);
    if (m != MEM_NIL)
      {
        int mark_p = 0;

				     YAMAMOTO Mitsuharu
				[email-masked]