diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/src/alloc.c b/src/alloc.c index 419c5e558b4..f69c65dedc1 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | /* Storage allocation and gc for GNU Emacs Lisp interpreter. | 1 | /* Storage allocation and gc for GNU Emacs Lisp interpreter. |
| 2 | 2 | ||
| 3 | Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2022 Free Software | 3 | Copyright (C) 1985-2022 Free Software Foundation, Inc. |
| 4 | Foundation, Inc. | ||
| 5 | 4 | ||
| 6 | This file is part of GNU Emacs. | 5 | This file is part of GNU Emacs. |
| 7 | 6 | ||
| @@ -46,6 +45,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 46 | #include "blockinput.h" | 45 | #include "blockinput.h" |
| 47 | #include "pdumper.h" | 46 | #include "pdumper.h" |
| 48 | #include "termhooks.h" /* For struct terminal. */ | 47 | #include "termhooks.h" /* For struct terminal. */ |
| 48 | #include "itree.h" | ||
| 49 | #ifdef HAVE_WINDOW_SYSTEM | 49 | #ifdef HAVE_WINDOW_SYSTEM |
| 50 | #include TERM_HEADER | 50 | #include TERM_HEADER |
| 51 | #endif /* HAVE_WINDOW_SYSTEM */ | 51 | #endif /* HAVE_WINDOW_SYSTEM */ |
| @@ -3129,6 +3129,11 @@ cleanup_vector (struct Lisp_Vector *vector) | |||
| 3129 | 3129 | ||
| 3130 | if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BIGNUM)) | 3130 | if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BIGNUM)) |
| 3131 | mpz_clear (PSEUDOVEC_STRUCT (vector, Lisp_Bignum)->value); | 3131 | mpz_clear (PSEUDOVEC_STRUCT (vector, Lisp_Bignum)->value); |
| 3132 | else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_OVERLAY)) | ||
| 3133 | { | ||
| 3134 | struct Lisp_Overlay *ol = PSEUDOVEC_STRUCT (vector, Lisp_Overlay); | ||
| 3135 | xfree (ol->interval); | ||
| 3136 | } | ||
| 3132 | else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FINALIZER)) | 3137 | else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FINALIZER)) |
| 3133 | unchain_finalizer (PSEUDOVEC_STRUCT (vector, Lisp_Finalizer)); | 3138 | unchain_finalizer (PSEUDOVEC_STRUCT (vector, Lisp_Finalizer)); |
| 3134 | else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT)) | 3139 | else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT)) |
| @@ -3697,18 +3702,20 @@ build_symbol_with_pos (Lisp_Object symbol, Lisp_Object position) | |||
| 3697 | return val; | 3702 | return val; |
| 3698 | } | 3703 | } |
| 3699 | 3704 | ||
| 3700 | /* Return a new overlay with specified START, END and PLIST. */ | 3705 | /* Return a new (deleted) overlay with PLIST. */ |
| 3701 | 3706 | ||
| 3702 | Lisp_Object | 3707 | Lisp_Object |
| 3703 | build_overlay (Lisp_Object start, Lisp_Object end, Lisp_Object plist) | 3708 | build_overlay (bool front_advance, bool rear_advance, |
| 3709 | Lisp_Object plist) | ||
| 3704 | { | 3710 | { |
| 3705 | struct Lisp_Overlay *p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Overlay, plist, | 3711 | struct Lisp_Overlay *p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Overlay, plist, |
| 3706 | PVEC_OVERLAY); | 3712 | PVEC_OVERLAY); |
| 3707 | Lisp_Object overlay = make_lisp_ptr (p, Lisp_Vectorlike); | 3713 | Lisp_Object overlay = make_lisp_ptr (p, Lisp_Vectorlike); |
| 3708 | OVERLAY_START (overlay) = start; | 3714 | struct itree_node *node = xmalloc (sizeof (*node)); |
| 3709 | OVERLAY_END (overlay) = end; | 3715 | itree_node_init (node, front_advance, rear_advance, overlay); |
| 3716 | p->interval = node; | ||
| 3717 | p->buffer = NULL; | ||
| 3710 | set_overlay_plist (overlay, plist); | 3718 | set_overlay_plist (overlay, plist); |
| 3711 | p->next = NULL; | ||
| 3712 | return overlay; | 3719 | return overlay; |
| 3713 | } | 3720 | } |
| 3714 | 3721 | ||
| @@ -5938,8 +5945,7 @@ visit_buffer_root (struct gc_root_visitor visitor, | |||
| 5938 | /* Buffers that are roots don't have intervals, an undo list, or | 5945 | /* Buffers that are roots don't have intervals, an undo list, or |
| 5939 | other constructs that real buffers have. */ | 5946 | other constructs that real buffers have. */ |
| 5940 | eassert (buffer->base_buffer == NULL); | 5947 | eassert (buffer->base_buffer == NULL); |
| 5941 | eassert (buffer->overlays_before == NULL); | 5948 | eassert (buffer->overlays == NULL); |
| 5942 | eassert (buffer->overlays_after == NULL); | ||
| 5943 | 5949 | ||
| 5944 | /* Visit the buffer-locals. */ | 5950 | /* Visit the buffer-locals. */ |
| 5945 | visit_vectorlike_root (visitor, (struct Lisp_Vector *) buffer, type); | 5951 | visit_vectorlike_root (visitor, (struct Lisp_Vector *) buffer, type); |
| @@ -6273,6 +6279,11 @@ garbage_collect (void) | |||
| 6273 | image_prune_animation_caches (false); | 6279 | image_prune_animation_caches (false); |
| 6274 | #endif | 6280 | #endif |
| 6275 | 6281 | ||
| 6282 | /* ELisp code run by `gc-post-hook' could result in itree iteration, | ||
| 6283 | which must not happen while the itree is already busy. See | ||
| 6284 | bug#58639. */ | ||
| 6285 | eassert (!itree_iterator_busy_p ()); | ||
| 6286 | |||
| 6276 | if (!NILP (Vpost_gc_hook)) | 6287 | if (!NILP (Vpost_gc_hook)) |
| 6277 | { | 6288 | { |
| 6278 | specpdl_ref gc_count = inhibit_garbage_collection (); | 6289 | specpdl_ref gc_count = inhibit_garbage_collection (); |
| @@ -6495,16 +6506,25 @@ mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype) | |||
| 6495 | /* Mark the chain of overlays starting at PTR. */ | 6506 | /* Mark the chain of overlays starting at PTR. */ |
| 6496 | 6507 | ||
| 6497 | static void | 6508 | static void |
| 6498 | mark_overlay (struct Lisp_Overlay *ptr) | 6509 | mark_overlay (struct Lisp_Overlay *ov) |
| 6499 | { | 6510 | { |
| 6500 | for (; ptr && !vectorlike_marked_p (&ptr->header); ptr = ptr->next) | 6511 | /* We don't mark the `interval_node` object, because it is managed manually |
| 6501 | { | 6512 | rather than by the GC. */ |
| 6502 | set_vectorlike_marked (&ptr->header); | 6513 | eassert (BASE_EQ (ov->interval->data, make_lisp_ptr (ov, Lisp_Vectorlike))); |
| 6503 | /* These two are always markers and can be marked fast. */ | 6514 | set_vectorlike_marked (&ov->header); |
| 6504 | set_vectorlike_marked (&XMARKER (ptr->start)->header); | 6515 | mark_object (ov->plist); |
| 6505 | set_vectorlike_marked (&XMARKER (ptr->end)->header); | 6516 | } |
| 6506 | mark_object (ptr->plist); | 6517 | |
| 6507 | } | 6518 | /* Mark the overlay subtree rooted at NODE. */ |
| 6519 | |||
| 6520 | static void | ||
| 6521 | mark_overlays (struct itree_node *node) | ||
| 6522 | { | ||
| 6523 | if (node == NULL) | ||
| 6524 | return; | ||
| 6525 | mark_object (node->data); | ||
| 6526 | mark_overlays (node->left); | ||
| 6527 | mark_overlays (node->right); | ||
| 6508 | } | 6528 | } |
| 6509 | 6529 | ||
| 6510 | /* Mark Lisp_Objects and special pointers in BUFFER. */ | 6530 | /* Mark Lisp_Objects and special pointers in BUFFER. */ |
| @@ -6528,8 +6548,8 @@ mark_buffer (struct buffer *buffer) | |||
| 6528 | if (!BUFFER_LIVE_P (buffer)) | 6548 | if (!BUFFER_LIVE_P (buffer)) |
| 6529 | mark_object (BVAR (buffer, undo_list)); | 6549 | mark_object (BVAR (buffer, undo_list)); |
| 6530 | 6550 | ||
| 6531 | mark_overlay (buffer->overlays_before); | 6551 | if (buffer->overlays) |
| 6532 | mark_overlay (buffer->overlays_after); | 6552 | mark_overlays (buffer->overlays->root); |
| 6533 | 6553 | ||
| 6534 | /* If this is an indirect buffer, mark its base buffer. */ | 6554 | /* If this is an indirect buffer, mark its base buffer. */ |
| 6535 | if (buffer->base_buffer && | 6555 | if (buffer->base_buffer && |