From cf95bb0213908a4caab65dccfa67b4f1572babe2 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 30 Aug 2020 23:40:11 -0700 Subject: [PATCH] Avoid some false matches in mark_maybe_pointer MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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. --- src/alloc.c | 84 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 14 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index e057107f98c..5453c54d931 100644 --- a/src/alloc.c +++ b/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; -- 2.39.5