Avoid some false matches in mark_maybe_pointer
This lets Emacs avoid marking some garbage as if it were in use. On one test platform (RHEL 7.8, Intel Xeon Silver 4116) it sped up ‘cd lisp; make compile-always’ by a bit over 1%. * src/alloc.c (live_string_holding, live_cons_holding) (live_symbol_holding, live_large_vector_holding) (live_small_vector_holding): Count only pointers that point to a struct component, or are a tagged pointer to the start of the struct. Exception: for non-bool-vector pseudovectors, count any pointer past the header, since it’s too much of a pain to write code for every pseudovector. (live_vector_pointer): New function.
This commit is contained in:
parent
aa1b586a1a
commit
cf95bb0213
1 changed files with 70 additions and 14 deletions
84
src/alloc.c
84
src/alloc.c
|
@ -4457,9 +4457,17 @@ live_string_holding (struct mem_node *m, void *p)
|
|||
must not be on the free-list. */
|
||||
if (0 <= offset && offset < sizeof b->strings)
|
||||
{
|
||||
struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0];
|
||||
if (s->u.s.data)
|
||||
return s;
|
||||
ptrdiff_t off = offset % sizeof b->strings[0];
|
||||
if (off == Lisp_String
|
||||
|| off == 0
|
||||
|| off == offsetof (struct Lisp_String, u.s.size_byte)
|
||||
|| off == offsetof (struct Lisp_String, u.s.intervals)
|
||||
|| off == offsetof (struct Lisp_String, u.s.data))
|
||||
{
|
||||
struct Lisp_String *s = p = cp -= off;
|
||||
if (s->u.s.data)
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -4489,9 +4497,15 @@ live_cons_holding (struct mem_node *m, void *p)
|
|||
&& (b != cons_block
|
||||
|| offset / sizeof b->conses[0] < cons_block_index))
|
||||
{
|
||||
struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0];
|
||||
if (!deadp (s->u.s.car))
|
||||
return s;
|
||||
ptrdiff_t off = offset % sizeof b->conses[0];
|
||||
if (off == Lisp_Cons
|
||||
|| off == 0
|
||||
|| off == offsetof (struct Lisp_Cons, u.s.u.cdr))
|
||||
{
|
||||
struct Lisp_Cons *s = p = cp -= off;
|
||||
if (!deadp (s->u.s.car))
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -4522,9 +4536,23 @@ live_symbol_holding (struct mem_node *m, void *p)
|
|||
&& (b != symbol_block
|
||||
|| offset / sizeof b->symbols[0] < symbol_block_index))
|
||||
{
|
||||
struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0];
|
||||
if (!deadp (s->u.s.function))
|
||||
return s;
|
||||
ptrdiff_t off = offset % sizeof b->symbols[0];
|
||||
if (off == Lisp_Symbol
|
||||
|
||||
/* Use u's offset since '|| off == 0' would run afoul of gcc
|
||||
-Wlogical-op, as Lisp_Symbol happens to be zero. */
|
||||
|| off == offsetof (struct Lisp_Symbol, u)
|
||||
|
||||
|| off == offsetof (struct Lisp_Symbol, u.s.name)
|
||||
|| off == offsetof (struct Lisp_Symbol, u.s.val)
|
||||
|| off == offsetof (struct Lisp_Symbol, u.s.function)
|
||||
|| off == offsetof (struct Lisp_Symbol, u.s.plist)
|
||||
|| off == offsetof (struct Lisp_Symbol, u.s.next))
|
||||
{
|
||||
struct Lisp_Symbol *s = p = cp -= off;
|
||||
if (!deadp (s->u.s.function))
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -4571,6 +4599,37 @@ live_float_p (struct mem_node *m, void *p)
|
|||
return live_float_holding (m, p) == p;
|
||||
}
|
||||
|
||||
/* Return VECTOR if P points within it, NULL otherwise. */
|
||||
|
||||
static struct Lisp_Vector *
|
||||
live_vector_pointer (struct Lisp_Vector *vector, void *p)
|
||||
{
|
||||
void *vvector = vector;
|
||||
char *cvector = vvector;
|
||||
char *cp = p;
|
||||
ptrdiff_t offset = cp - cvector;
|
||||
return ((offset == Lisp_Vectorlike
|
||||
|| offset == 0
|
||||
|| (sizeof vector->header <= offset
|
||||
&& offset < vector_nbytes (vector)
|
||||
&& (! (vector->header.size & PSEUDOVECTOR_FLAG)
|
||||
? (offsetof (struct Lisp_Vector, contents) <= offset
|
||||
&& (((offset - offsetof (struct Lisp_Vector, contents))
|
||||
% word_size)
|
||||
== 0))
|
||||
/* For non-bool-vector pseudovectors, treat any pointer
|
||||
past the header as valid since it's too much of a pain
|
||||
to write special-case code for every pseudovector. */
|
||||
: (! PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR)
|
||||
|| offset == offsetof (struct Lisp_Bool_Vector, size)
|
||||
|| (offsetof (struct Lisp_Bool_Vector, data) <= offset
|
||||
&& (((offset
|
||||
- offsetof (struct Lisp_Bool_Vector, data))
|
||||
% sizeof (bits_word))
|
||||
== 0))))))
|
||||
? vector : NULL);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
@ -4579,10 +4638,7 @@ static struct Lisp_Vector *
|
|||
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;
|
||||
return live_vector_pointer (large_vector_vec (m->start), p);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -4612,7 +4668,7 @@ live_small_vector_holding (struct mem_node *m, void *p)
|
|||
{
|
||||
struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
|
||||
if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
|
||||
return vector;
|
||||
return live_vector_pointer (vector, vp);
|
||||
vector = next;
|
||||
}
|
||||
return NULL;
|
||||
|
|
Loading…
Add table
Reference in a new issue