diff options
| author | Paul Eggert | 2020-08-30 23:40:11 -0700 |
|---|---|---|
| committer | Paul Eggert | 2020-08-31 00:05:56 -0700 |
| commit | cf95bb0213908a4caab65dccfa67b4f1572babe2 (patch) | |
| tree | b1947e6458d3c6fb992320deee00884c80b2c949 /src/alloc.c | |
| parent | aa1b586a1afaa88e5a9521a7640feefc2c12f009 (diff) | |
| download | emacs-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.c | 84 |
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 | |||
| 4604 | static struct Lisp_Vector * | ||
| 4605 | live_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 * | |||
| 4579 | live_large_vector_holding (struct mem_node *m, void *p) | 4638 | live_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 | ||
| 4588 | static bool | 4644 | static 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; |