Streamline live_*_holding

(live_string_holding, live_cons_holding, live_symbol_holding)
(live_float_p, live_vector_holding):
Assert that m->type is correct, instead of testing this at
runtime.  All callers changed.
(live_large_vector_holding, live_small_vector_holding):
Now two functions instead of the old live_vector_holding.
All callers changed.
(live_large_vector_p, live_small_vector_p):
Now two functions instead of the old live_vector_p.
All callers changed.
(mark_maybe_object): Ignore Lisp_Type_Unused0 quickly too,
since that cannot possibly be an object.
(CHECK_LIVE, CHECK_ALLOCATED_AND_LIVE):
New arg MEM_TYPE.  All callers changed.
(CHECK_ALLOCATED_AND_LIVE_SYMBOL): Simplify by combining
GC_CHECK_MARKED_OBJECTS code.
This commit is contained in:
Paul Eggert 2020-06-04 18:46:11 -07:00
parent 4dcf8f2205
commit 8ee367fe86

View file

@ -4449,21 +4449,19 @@ mem_delete_fixup (struct mem_node *x)
static struct Lisp_String *
live_string_holding (struct mem_node *m, void *p)
{
if (m->type == MEM_TYPE_STRING)
{
struct string_block *b = m->start;
char *cp = p;
ptrdiff_t offset = cp - (char *) &b->strings[0];
eassert (m->type == MEM_TYPE_STRING);
struct string_block *b = m->start;
char *cp = p;
ptrdiff_t offset = cp - (char *) &b->strings[0];
/* P must point into a Lisp_String structure, and it
must not be on the free-list. */
if (0 <= offset && offset < sizeof b->strings)
{
cp = ptr_bounds_copy (cp, b);
struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0];
if (s->u.s.data)
return s;
}
/* P must point into a Lisp_String structure, and it
must not be on the free-list. */
if (0 <= offset && offset < sizeof b->strings)
{
cp = ptr_bounds_copy (cp, b);
struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0];
if (s->u.s.data)
return s;
}
return NULL;
}
@ -4481,24 +4479,22 @@ live_string_p (struct mem_node *m, void *p)
static struct Lisp_Cons *
live_cons_holding (struct mem_node *m, void *p)
{
if (m->type == MEM_TYPE_CONS)
{
struct cons_block *b = m->start;
char *cp = p;
ptrdiff_t offset = cp - (char *) &b->conses[0];
eassert (m->type == MEM_TYPE_CONS);
struct cons_block *b = m->start;
char *cp = p;
ptrdiff_t offset = cp - (char *) &b->conses[0];
/* P must point into a Lisp_Cons, not be
one of the unused cells in the current cons block,
and not be on the free-list. */
if (0 <= offset && offset < sizeof b->conses
&& (b != cons_block
|| offset / sizeof b->conses[0] < cons_block_index))
{
cp = ptr_bounds_copy (cp, b);
struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0];
if (!deadp (s->u.s.car))
return s;
}
/* P must point into a Lisp_Cons, not be
one of the unused cells in the current cons block,
and not be on the free-list. */
if (0 <= offset && offset < sizeof b->conses
&& (b != cons_block
|| offset / sizeof b->conses[0] < cons_block_index))
{
cp = ptr_bounds_copy (cp, b);
struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0];
if (!deadp (s->u.s.car))
return s;
}
return NULL;
}
@ -4517,24 +4513,22 @@ live_cons_p (struct mem_node *m, void *p)
static struct Lisp_Symbol *
live_symbol_holding (struct mem_node *m, void *p)
{
if (m->type == MEM_TYPE_SYMBOL)
{
struct symbol_block *b = m->start;
char *cp = p;
ptrdiff_t offset = cp - (char *) &b->symbols[0];
eassert (m->type == MEM_TYPE_SYMBOL);
struct symbol_block *b = m->start;
char *cp = p;
ptrdiff_t offset = cp - (char *) &b->symbols[0];
/* P must point into the Lisp_Symbol, not be
one of the unused cells in the current symbol block,
and not be on the free-list. */
if (0 <= offset && offset < sizeof b->symbols
&& (b != symbol_block
|| offset / sizeof b->symbols[0] < symbol_block_index))
{
cp = ptr_bounds_copy (cp, b);
struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0];
if (!deadp (s->u.s.function))
return s;
}
/* P must point into the Lisp_Symbol, not be
one of the unused cells in the current symbol block,
and not be on the free-list. */
if (0 <= offset && offset < sizeof b->symbols
&& (b != symbol_block
|| offset / sizeof b->symbols[0] < symbol_block_index))
{
cp = ptr_bounds_copy (cp, b);
struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0];
if (!deadp (s->u.s.function))
return s;
}
return NULL;
}
@ -4552,66 +4546,70 @@ live_symbol_p (struct mem_node *m, void *p)
static bool
live_float_p (struct mem_node *m, void *p)
{
if (m->type == MEM_TYPE_FLOAT)
{
struct float_block *b = m->start;
char *cp = p;
ptrdiff_t offset = cp - (char *) &b->floats[0];
eassert (m->type == MEM_TYPE_FLOAT);
struct float_block *b = m->start;
char *cp = p;
ptrdiff_t offset = cp - (char *) &b->floats[0];
/* P must point to the start of a Lisp_Float and not be
one of the unused cells in the current float block. */
return (0 <= offset && offset < sizeof b->floats
&& offset % sizeof b->floats[0] == 0
&& (b != float_block
|| offset / sizeof b->floats[0] < float_block_index));
}
else
return 0;
/* P must point to the start of a Lisp_Float and not be
one of the unused cells in the current float block. */
return (0 <= offset && offset < sizeof b->floats
&& offset % sizeof b->floats[0] == 0
&& (b != float_block
|| offset / sizeof b->floats[0] < float_block_index));
}
/* If P is a pointer to a live vector-like object, return the object.
/* If P is a pointer to a live, large vector-like object, return the object.
Otherwise, return nil.
M is a pointer to the mem_block for P. */
static struct Lisp_Vector *
live_vector_holding (struct mem_node *m, void *p)
live_large_vector_holding (struct mem_node *m, void *p)
{
eassert (m->type == MEM_TYPE_VECTORLIKE);
struct Lisp_Vector *vp = p;
struct Lisp_Vector *vector = large_vector_vec (m->start);
struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
return vector <= vp && vp < next ? vector : NULL;
}
if (m->type == MEM_TYPE_VECTOR_BLOCK)
{
/* This memory node corresponds to a vector block. */
struct vector_block *block = m->start;
struct Lisp_Vector *vector = (struct Lisp_Vector *) block->data;
static bool
live_large_vector_p (struct mem_node *m, void *p)
{
return live_large_vector_holding (m, p) == p;
}
/* P is in the block's allocation range. Scan the block
up to P and see whether P points to the start of some
vector which is not on a free list. FIXME: check whether
some allocation patterns (probably a lot of short vectors)
may cause a substantial overhead of this loop. */
while (VECTOR_IN_BLOCK (vector, block) && vector <= vp)
{
struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
return vector;
vector = next;
}
}
else if (m->type == MEM_TYPE_VECTORLIKE)
/* If P is a pointer to a live, small vector-like object, return the object.
Otherwise, return NULL.
M is a pointer to the mem_block for P. */
static struct Lisp_Vector *
live_small_vector_holding (struct mem_node *m, void *p)
{
eassert (m->type == MEM_TYPE_VECTOR_BLOCK);
struct Lisp_Vector *vp = p;
struct vector_block *block = m->start;
struct Lisp_Vector *vector = (struct Lisp_Vector *) block->data;
/* P is in the block's allocation range. Scan the block
up to P and see whether P points to the start of some
vector which is not on a free list. FIXME: check whether
some allocation patterns (probably a lot of short vectors)
may cause a substantial overhead of this loop. */
while (VECTOR_IN_BLOCK (vector, block) && vector <= vp)
{
/* This memory node corresponds to a large vector. */
struct Lisp_Vector *vector = large_vector_vec (m->start);
struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
if (vector <= vp && vp < next)
if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
return vector;
vector = next;
}
return NULL;
}
static bool
live_vector_p (struct mem_node *m, void *p)
live_small_vector_p (struct mem_node *m, void *p)
{
return live_vector_holding (m, p) == p;
return live_small_vector_holding (m, p) == p;
}
/* Mark OBJ if we can prove it's a Lisp_Object. */
@ -4623,10 +4621,24 @@ mark_maybe_object (Lisp_Object obj)
VALGRIND_MAKE_MEM_DEFINED (&obj, sizeof (obj));
#endif
if (FIXNUMP (obj))
return;
int type_tag = XTYPE (obj);
intptr_t offset;
void *po = XPNTR (obj);
switch (type_tag)
{
case_Lisp_Int: case Lisp_Type_Unused0:
return;
case Lisp_Symbol:
offset = (intptr_t) lispsym;
break;
default:
offset = 0;
break;
}
void *po = (char *) XLP (obj) + (offset - LISP_WORD_TAG (type_tag));
/* If the pointer is in the dump image and the dump has a record
of the object starting at the place where the pointer points, we
@ -4638,7 +4650,7 @@ mark_maybe_object (Lisp_Object obj)
/* Don't use pdumper_object_p_precise here! It doesn't check the
tag bits. OBJ here might be complete garbage, so we need to
verify both the pointer and the tag. */
if (XTYPE (obj) == pdumper_find_object_type (po))
if (pdumper_find_object_type (po) == type_tag)
mark_object (obj);
return;
}
@ -4649,30 +4661,33 @@ mark_maybe_object (Lisp_Object obj)
{
bool mark_p = false;
switch (XTYPE (obj))
switch (type_tag)
{
case Lisp_String:
mark_p = live_string_p (m, po);
mark_p = m->type == MEM_TYPE_STRING && live_string_p (m, po);
break;
case Lisp_Cons:
mark_p = live_cons_p (m, po);
mark_p = m->type == MEM_TYPE_CONS && live_cons_p (m, po);
break;
case Lisp_Symbol:
mark_p = live_symbol_p (m, po);
mark_p = m->type == MEM_TYPE_SYMBOL && live_symbol_p (m, po);
break;
case Lisp_Float:
mark_p = live_float_p (m, po);
mark_p = m->type == MEM_TYPE_FLOAT && live_float_p (m, po);
break;
case Lisp_Vectorlike:
mark_p = live_vector_p (m, po);
mark_p = (m->type == MEM_TYPE_VECTOR_BLOCK
? live_small_vector_p (m, po)
: (m->type == MEM_TYPE_VECTORLIKE
&& live_large_vector_p (m, po)));
break;
default:
break;
eassume (false);
}
if (mark_p)
@ -4756,9 +4771,17 @@ mark_maybe_pointer (void *p)
break;
case MEM_TYPE_VECTORLIKE:
{
struct Lisp_Vector *h = live_large_vector_holding (m, p);
if (!h)
return;
obj = make_lisp_ptr (h, Lisp_Vectorlike);
}
break;
case MEM_TYPE_VECTOR_BLOCK:
{
struct Lisp_Vector *h = live_vector_holding (m, p);
struct Lisp_Vector *h = live_small_vector_holding (m, p);
if (!h)
return;
obj = make_lisp_ptr (h, Lisp_Vectorlike);
@ -5176,8 +5199,10 @@ valid_lisp_object_p (Lisp_Object obj)
return live_float_p (m, p);
case MEM_TYPE_VECTORLIKE:
return live_large_vector_p (m, p);
case MEM_TYPE_VECTOR_BLOCK:
return live_vector_p (m, p);
return live_small_vector_p (m, p);
default:
break;
@ -6551,19 +6576,19 @@ mark_object (Lisp_Object arg)
/* Check that the object pointed to by PO is live, using predicate
function LIVEP. */
#define CHECK_LIVE(LIVEP) \
#define CHECK_LIVE(LIVEP, MEM_TYPE) \
do { \
if (pdumper_object_p (po)) \
break; \
if (!LIVEP (m, po)) \
if (! (m->type == MEM_TYPE && LIVEP (m, po))) \
emacs_abort (); \
} while (0)
/* Check both of the above conditions, for non-symbols. */
#define CHECK_ALLOCATED_AND_LIVE(LIVEP) \
#define CHECK_ALLOCATED_AND_LIVE(LIVEP, MEM_TYPE) \
do { \
CHECK_ALLOCATED (); \
CHECK_LIVE (LIVEP); \
CHECK_LIVE (LIVEP, MEM_TYPE); \
} while (false)
/* Check both of the above conditions, for symbols. */
@ -6572,15 +6597,14 @@ mark_object (Lisp_Object arg)
if (!c_symbol_p (ptr)) \
{ \
CHECK_ALLOCATED (); \
CHECK_LIVE (live_symbol_p); \
CHECK_LIVE (live_symbol_p, MEM_TYPE_SYMBOL); \
} \
} while (false)
#else /* not GC_CHECK_MARKED_OBJECTS */
#define CHECK_LIVE(LIVEP) ((void) 0)
#define CHECK_ALLOCATED_AND_LIVE(LIVEP) ((void) 0)
#define CHECK_ALLOCATED_AND_LIVE_SYMBOL() ((void) 0)
#define CHECK_ALLOCATED_AND_LIVE(LIVEP, MEM_TYPE) ((void) 0)
#define CHECK_ALLOCATED_AND_LIVE_SYMBOL() ((void) 0)
#endif /* not GC_CHECK_MARKED_OBJECTS */
@ -6591,7 +6615,7 @@ mark_object (Lisp_Object arg)
register struct Lisp_String *ptr = XSTRING (obj);
if (string_marked_p (ptr))
break;
CHECK_ALLOCATED_AND_LIVE (live_string_p);
CHECK_ALLOCATED_AND_LIVE (live_string_p, MEM_TYPE_STRING);
set_string_marked (ptr);
mark_interval_tree (ptr->u.s.intervals);
#ifdef GC_CHECK_STRING_BYTES
@ -6609,21 +6633,21 @@ mark_object (Lisp_Object arg)
if (vector_marked_p (ptr))
break;
#ifdef GC_CHECK_MARKED_OBJECTS
if (!pdumper_object_p (po))
{
m = mem_find (po);
if (m == MEM_NIL && !SUBRP (obj) && !main_thread_p (po))
emacs_abort ();
}
#endif /* GC_CHECK_MARKED_OBJECTS */
enum pvec_type pvectype
= PSEUDOVECTOR_TYPE (ptr);
if (pvectype != PVEC_SUBR &&
!main_thread_p (po))
CHECK_LIVE (live_vector_p);
#ifdef GC_CHECK_MARKED_OBJECTS
if (!pdumper_object_p (po) && !SUBRP (obj) && !main_thread_p (po))
{
m = mem_find (po);
if (m == MEM_NIL)
emacs_abort ();
if (m->type == MEM_TYPE_VECTORLIKE)
CHECK_LIVE (live_large_vector_p, MEM_TYPE_VECTORLIKE);
else
CHECK_LIVE (live_small_vector_p, MEM_TYPE_VECTOR_BLOCK);
}
#endif
switch (pvectype)
{
@ -6734,7 +6758,7 @@ mark_object (Lisp_Object arg)
struct Lisp_Cons *ptr = XCONS (obj);
if (cons_marked_p (ptr))
break;
CHECK_ALLOCATED_AND_LIVE (live_cons_p);
CHECK_ALLOCATED_AND_LIVE (live_cons_p, MEM_TYPE_CONS);
set_cons_marked (ptr);
/* If the cdr is nil, avoid recursion for the car. */
if (NILP (ptr->u.s.u.cdr))
@ -6752,7 +6776,7 @@ mark_object (Lisp_Object arg)
}
case Lisp_Float:
CHECK_ALLOCATED_AND_LIVE (live_float_p);
CHECK_ALLOCATED_AND_LIVE (live_float_p, MEM_TYPE_FLOAT);
/* Do not mark floats stored in a dump image: these floats are
"cold" and do not have mark bits. */
if (pdumper_object_p (XFLOAT (obj)))