Commit 4f5c1376 authored by Gerd Moellmann's avatar Gerd Moellmann
Browse files

(mark_object) [GC_CHECK_MARKED_OBJECTS]: Check that no

bogus objects are marked.  This slows down GC by ~80 percent, but
it might be worth trying when debugging GC-related problems.
This feature requires conservative stack marking to be enabled.
parent c8bb8167
...@@ -3785,6 +3785,10 @@ mark_object (argptr) ...@@ -3785,6 +3785,10 @@ mark_object (argptr)
{ {
Lisp_Object *objptr = argptr; Lisp_Object *objptr = argptr;
register Lisp_Object obj; register Lisp_Object obj;
#ifdef GC_CHECK_MARKED_OBJECTS
void *po;
struct mem_node *m;
#endif
loop: loop:
obj = *objptr; obj = *objptr;
...@@ -3798,22 +3802,82 @@ mark_object (argptr) ...@@ -3798,22 +3802,82 @@ mark_object (argptr)
if (last_marked_index == LAST_MARKED_SIZE) if (last_marked_index == LAST_MARKED_SIZE)
last_marked_index = 0; last_marked_index = 0;
/* Perform some sanity checks on the objects marked here. Abort if
we encounter an object we know is bogus. This increases GC time
by ~80%, and requires compilation with GC_MARK_STACK != 0. */
#ifdef GC_CHECK_MARKED_OBJECTS
po = (void *) XPNTR (obj);
/* Check that the object pointed to by PO is known to be a Lisp
structure allocated from the heap. */
#define CHECK_ALLOCATED() \
do { \
m = mem_find (po); \
if (m == MEM_NIL) \
abort (); \
} while (0)
/* Check that the object pointed to by PO is live, using predicate
function LIVEP. */
#define CHECK_LIVE(LIVEP) \
do { \
if (!LIVEP (m, po)) \
abort (); \
} while (0)
/* Check both of the above conditions. */
#define CHECK_ALLOCATED_AND_LIVE(LIVEP) \
do { \
CHECK_ALLOCATED (); \
CHECK_LIVE (LIVEP); \
} while (0) \
#else /* not GC_CHECK_MARKED_OBJECTS */
#define CHECK_ALLOCATED() (void) 0
#define CHECK_LIVE(LIVEP) (void) 0
#define CHECK_ALLOCATED_AND_LIVE(LIVEP) (void) 0
#endif /* not GC_CHECK_MARKED_OBJECTS */
switch (SWITCH_ENUM_CAST (XGCTYPE (obj))) switch (SWITCH_ENUM_CAST (XGCTYPE (obj)))
{ {
case Lisp_String: case Lisp_String:
{ {
register struct Lisp_String *ptr = XSTRING (obj); register struct Lisp_String *ptr = XSTRING (obj);
CHECK_ALLOCATED_AND_LIVE (live_string_p);
MARK_INTERVAL_TREE (ptr->intervals); MARK_INTERVAL_TREE (ptr->intervals);
MARK_STRING (ptr); MARK_STRING (ptr);
} }
break; break;
case Lisp_Vectorlike: case Lisp_Vectorlike:
#ifdef GC_CHECK_MARKED_OBJECTS
m = mem_find (po);
if (m == MEM_NIL && !GC_SUBRP (obj)
&& po != &buffer_defaults
&& po != &buffer_local_symbols)
abort ();
#endif /* GC_CHECK_MARKED_OBJECTS */
if (GC_BUFFERP (obj)) if (GC_BUFFERP (obj))
{ {
if (!XMARKBIT (XBUFFER (obj)->name)) if (!XMARKBIT (XBUFFER (obj)->name))
{
#ifdef GC_CHECK_MARKED_OBJECTS
if (po != &buffer_defaults && po != &buffer_local_symbols)
{
struct buffer *b;
for (b = all_buffers; b && b != po; b = b->next)
;
if (b == NULL)
abort ();
}
#endif /* GC_CHECK_MARKED_OBJECTS */
mark_buffer (obj); mark_buffer (obj);
} }
}
else if (GC_SUBRP (obj)) else if (GC_SUBRP (obj))
break; break;
else if (GC_COMPILEDP (obj)) else if (GC_COMPILEDP (obj))
...@@ -3829,6 +3893,8 @@ mark_object (argptr) ...@@ -3829,6 +3893,8 @@ mark_object (argptr)
if (size & ARRAY_MARK_FLAG) if (size & ARRAY_MARK_FLAG)
break; /* Already marked */ break; /* Already marked */
CHECK_LIVE (live_vector_p);
ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */
size &= PSEUDOVECTOR_SIZE_MASK; size &= PSEUDOVECTOR_SIZE_MASK;
for (i = 0; i < size; i++) /* and then mark its elements */ for (i = 0; i < size; i++) /* and then mark its elements */
...@@ -3850,6 +3916,7 @@ mark_object (argptr) ...@@ -3850,6 +3916,7 @@ mark_object (argptr)
if (size & ARRAY_MARK_FLAG) break; /* Already marked */ if (size & ARRAY_MARK_FLAG) break; /* Already marked */
ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */
CHECK_LIVE (live_vector_p);
mark_object (&ptr->name); mark_object (&ptr->name);
mark_object (&ptr->icon_name); mark_object (&ptr->icon_name);
mark_object (&ptr->title); mark_object (&ptr->title);
...@@ -3881,6 +3948,7 @@ mark_object (argptr) ...@@ -3881,6 +3948,7 @@ mark_object (argptr)
if (ptr->size & ARRAY_MARK_FLAG) if (ptr->size & ARRAY_MARK_FLAG)
break; /* Already marked */ break; /* Already marked */
CHECK_LIVE (live_vector_p);
ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */
} }
else if (GC_WINDOWP (obj)) else if (GC_WINDOWP (obj))
...@@ -3902,6 +3970,7 @@ mark_object (argptr) ...@@ -3902,6 +3970,7 @@ mark_object (argptr)
break; break;
/* Mark it. */ /* Mark it. */
CHECK_LIVE (live_vector_p);
ptr->size |= ARRAY_MARK_FLAG; ptr->size |= ARRAY_MARK_FLAG;
/* There is no Lisp data above The member CURRENT_MATRIX in /* There is no Lisp data above The member CURRENT_MATRIX in
...@@ -3932,6 +4001,7 @@ mark_object (argptr) ...@@ -3932,6 +4001,7 @@ mark_object (argptr)
break; break;
/* Mark it. */ /* Mark it. */
CHECK_LIVE (live_vector_p);
h->size |= ARRAY_MARK_FLAG; h->size |= ARRAY_MARK_FLAG;
/* Mark contents. */ /* Mark contents. */
...@@ -3967,6 +4037,7 @@ mark_object (argptr) ...@@ -3967,6 +4037,7 @@ mark_object (argptr)
register int i; register int i;
if (size & ARRAY_MARK_FLAG) break; /* Already marked */ if (size & ARRAY_MARK_FLAG) break; /* Already marked */
CHECK_LIVE (live_vector_p);
ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */
if (size & PSEUDOVECTOR_FLAG) if (size & PSEUDOVECTOR_FLAG)
size &= PSEUDOVECTOR_SIZE_MASK; size &= PSEUDOVECTOR_SIZE_MASK;
...@@ -3983,6 +4054,7 @@ mark_object (argptr) ...@@ -3983,6 +4054,7 @@ mark_object (argptr)
struct Lisp_Symbol *ptrx; struct Lisp_Symbol *ptrx;
if (XMARKBIT (ptr->plist)) break; if (XMARKBIT (ptr->plist)) break;
CHECK_ALLOCATED_AND_LIVE (live_symbol_p);
XMARK (ptr->plist); XMARK (ptr->plist);
mark_object ((Lisp_Object *) &ptr->value); mark_object ((Lisp_Object *) &ptr->value);
mark_object (&ptr->function); mark_object (&ptr->function);
...@@ -4010,6 +4082,7 @@ mark_object (argptr) ...@@ -4010,6 +4082,7 @@ mark_object (argptr)
break; break;
case Lisp_Misc: case Lisp_Misc:
CHECK_ALLOCATED_AND_LIVE (live_misc_p);
switch (XMISCTYPE (obj)) switch (XMISCTYPE (obj))
{ {
case Lisp_Misc_Marker: case Lisp_Misc_Marker:
...@@ -4074,6 +4147,7 @@ mark_object (argptr) ...@@ -4074,6 +4147,7 @@ mark_object (argptr)
{ {
register struct Lisp_Cons *ptr = XCONS (obj); register struct Lisp_Cons *ptr = XCONS (obj);
if (XMARKBIT (ptr->car)) break; if (XMARKBIT (ptr->car)) break;
CHECK_ALLOCATED_AND_LIVE (live_cons_p);
XMARK (ptr->car); XMARK (ptr->car);
/* If the cdr is nil, avoid recursion for the car. */ /* If the cdr is nil, avoid recursion for the car. */
if (EQ (ptr->cdr, Qnil)) if (EQ (ptr->cdr, Qnil))
...@@ -4088,6 +4162,7 @@ mark_object (argptr) ...@@ -4088,6 +4162,7 @@ mark_object (argptr)
} }
case Lisp_Float: case Lisp_Float:
CHECK_ALLOCATED_AND_LIVE (live_float_p);
XMARK (XFLOAT (obj)->type); XMARK (XFLOAT (obj)->type);
break; break;
...@@ -4097,6 +4172,10 @@ mark_object (argptr) ...@@ -4097,6 +4172,10 @@ mark_object (argptr)
default: default:
abort (); abort ();
} }
#undef CHECK_LIVE
#undef CHECK_ALLOCATED
#undef CHECK_ALLOCATED_AND_LIVE
} }
/* Mark the pointers in a buffer structure. */ /* Mark the pointers in a buffer structure. */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment