aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert2020-08-30 23:40:11 -0700
committerPaul Eggert2020-08-31 00:05:56 -0700
commitcf95bb0213908a4caab65dccfa67b4f1572babe2 (patch)
treeb1947e6458d3c6fb992320deee00884c80b2c949 /src/alloc.c
parentaa1b586a1afaa88e5a9521a7640feefc2c12f009 (diff)
downloademacs-cf95bb0213908a4caab65dccfa67b4f1572babe2.tar.gz
emacs-cf95bb0213908a4caab65dccfa67b4f1572babe2.zip
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.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c84
1 files 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)
4457 must not be on the free-list. */ 4457 must not be on the free-list. */
4458 if (0 <= offset && offset < sizeof b->strings) 4458 if (0 <= offset && offset < sizeof b->strings)
4459 { 4459 {
4460 struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0]; 4460 ptrdiff_t off = offset % sizeof b->strings[0];
4461 if (s->u.s.data) 4461 if (off == Lisp_String
4462 return s; 4462 || off == 0
4463 || off == offsetof (struct Lisp_String, u.s.size_byte)
4464 || off == offsetof (struct Lisp_String, u.s.intervals)
4465 || off == offsetof (struct Lisp_String, u.s.data))
4466 {
4467 struct Lisp_String *s = p = cp -= off;
4468 if (s->u.s.data)
4469 return s;
4470 }
4463 } 4471 }
4464 return NULL; 4472 return NULL;
4465} 4473}
@@ -4489,9 +4497,15 @@ live_cons_holding (struct mem_node *m, void *p)
4489 && (b != cons_block 4497 && (b != cons_block
4490 || offset / sizeof b->conses[0] < cons_block_index)) 4498 || offset / sizeof b->conses[0] < cons_block_index))
4491 { 4499 {
4492 struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0]; 4500 ptrdiff_t off = offset % sizeof b->conses[0];
4493 if (!deadp (s->u.s.car)) 4501 if (off == Lisp_Cons
4494 return s; 4502 || off == 0
4503 || off == offsetof (struct Lisp_Cons, u.s.u.cdr))
4504 {
4505 struct Lisp_Cons *s = p = cp -= off;
4506 if (!deadp (s->u.s.car))
4507 return s;
4508 }
4495 } 4509 }
4496 return NULL; 4510 return NULL;
4497} 4511}
@@ -4522,9 +4536,23 @@ live_symbol_holding (struct mem_node *m, void *p)
4522 && (b != symbol_block 4536 && (b != symbol_block
4523 || offset / sizeof b->symbols[0] < symbol_block_index)) 4537 || offset / sizeof b->symbols[0] < symbol_block_index))
4524 { 4538 {
4525 struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0]; 4539 ptrdiff_t off = offset % sizeof b->symbols[0];
4526 if (!deadp (s->u.s.function)) 4540 if (off == Lisp_Symbol
4527 return s; 4541
4542 /* Use u's offset since '|| off == 0' would run afoul of gcc
4543 -Wlogical-op, as Lisp_Symbol happens to be zero. */
4544 || off == offsetof (struct Lisp_Symbol, u)
4545
4546 || off == offsetof (struct Lisp_Symbol, u.s.name)
4547 || off == offsetof (struct Lisp_Symbol, u.s.val)
4548 || off == offsetof (struct Lisp_Symbol, u.s.function)
4549 || off == offsetof (struct Lisp_Symbol, u.s.plist)
4550 || off == offsetof (struct Lisp_Symbol, u.s.next))
4551 {
4552 struct Lisp_Symbol *s = p = cp -= off;
4553 if (!deadp (s->u.s.function))
4554 return s;
4555 }
4528 } 4556 }
4529 return NULL; 4557 return NULL;
4530} 4558}
@@ -4571,6 +4599,37 @@ live_float_p (struct mem_node *m, void *p)
4571 return live_float_holding (m, p) == p; 4599 return live_float_holding (m, p) == p;
4572} 4600}
4573 4601
4602/* Return VECTOR if P points within it, NULL otherwise. */
4603
4604static struct Lisp_Vector *
4605live_vector_pointer (struct Lisp_Vector *vector, void *p)
4606{
4607 void *vvector = vector;
4608 char *cvector = vvector;
4609 char *cp = p;
4610 ptrdiff_t offset = cp - cvector;
4611 return ((offset == Lisp_Vectorlike
4612 || offset == 0
4613 || (sizeof vector->header <= offset
4614 && offset < vector_nbytes (vector)
4615 && (! (vector->header.size & PSEUDOVECTOR_FLAG)
4616 ? (offsetof (struct Lisp_Vector, contents) <= offset
4617 && (((offset - offsetof (struct Lisp_Vector, contents))
4618 % word_size)
4619 == 0))
4620 /* For non-bool-vector pseudovectors, treat any pointer
4621 past the header as valid since it's too much of a pain
4622 to write special-case code for every pseudovector. */
4623 : (! PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR)
4624 || offset == offsetof (struct Lisp_Bool_Vector, size)
4625 || (offsetof (struct Lisp_Bool_Vector, data) <= offset
4626 && (((offset
4627 - offsetof (struct Lisp_Bool_Vector, data))
4628 % sizeof (bits_word))
4629 == 0))))))
4630 ? vector : NULL);
4631}
4632
4574/* If P is a pointer to a live, large vector-like object, return the object. 4633/* If P is a pointer to a live, large vector-like object, return the object.
4575 Otherwise, return nil. 4634 Otherwise, return nil.
4576 M is a pointer to the mem_block for P. */ 4635 M is a pointer to the mem_block for P. */
@@ -4579,10 +4638,7 @@ static struct Lisp_Vector *
4579live_large_vector_holding (struct mem_node *m, void *p) 4638live_large_vector_holding (struct mem_node *m, void *p)
4580{ 4639{
4581 eassert (m->type == MEM_TYPE_VECTORLIKE); 4640 eassert (m->type == MEM_TYPE_VECTORLIKE);
4582 struct Lisp_Vector *vp = p; 4641 return live_vector_pointer (large_vector_vec (m->start), p);
4583 struct Lisp_Vector *vector = large_vector_vec (m->start);
4584 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
4585 return vector <= vp && vp < next ? vector : NULL;
4586} 4642}
4587 4643
4588static bool 4644static bool
@@ -4612,7 +4668,7 @@ live_small_vector_holding (struct mem_node *m, void *p)
4612 { 4668 {
4613 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector)); 4669 struct Lisp_Vector *next = ADVANCE (vector, vector_nbytes (vector));
4614 if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE)) 4670 if (vp < next && !PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
4615 return vector; 4671 return live_vector_pointer (vector, vp);
4616 vector = next; 4672 vector = next;
4617 } 4673 }
4618 return NULL; 4674 return NULL;