aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorStefan Monnier2020-03-31 19:45:22 -0400
committerStefan Monnier2020-03-31 19:45:45 -0400
commitcddf85d256dda8db1fad50e8e766fd7694361b8f (patch)
treed6cd89343e879eedf1ca46be759b53388f529096 /src/alloc.c
parenta477a7b86ba7c59a90b18283cc86769c27de6c7c (diff)
downloademacs-cddf85d256dda8db1fad50e8e766fd7694361b8f.tar.gz
emacs-cddf85d256dda8db1fad50e8e766fd7694361b8f.zip
Remove `all_buffers` and the associated `next` field of buffers
* src/alloc.c (enum mem_type): Remove MEM_TYPE_BUFFER. (allocate_buffer): Allocate like any other pseudovector. Don't register on `all_buffers` any more. (live_buffer_holding, live_buffer_p): Delete functions. (mark_maybe_object, valid_lisp_object_p): Don't pay attention to MEM_TYPE_BUFFER any more. (garbage_collect): Only compact the live buffers. (mark_buffer): Mark the undo_list of dead buffers here. (mark_object): Buffers are normal pseudovectors now. (sweep_buffers): Don't do the actual sweep here, just cleanup the markers and only for live buffers. * src/buffer.c (all_buffers): Remove variable. (Fkill_buffer): Don't check indirect dead buffers. Set the undo_list before we remove ourselves from the list of live buffers. (Fbuffer_swap_text, Fset_buffer_multibyte): Don't check indirect dead buffers. (init_buffer_once): Don't set `all_buffers`. (init_buffer): Don't map new memory for dead buffers. * src/buffer.h (struct buffer): Remove `next` field. (FOR_EACH_BUFFER): Remove macro. * src/pdumper.c (dump_buffer): Don't dump the `next` field.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c106
1 files changed, 24 insertions, 82 deletions
diff --git a/src/alloc.c b/src/alloc.c
index eed73bcdc4e..cc9ba8dbf50 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -432,7 +432,6 @@ inline static void set_interval_marked (INTERVAL i);
432enum mem_type 432enum mem_type
433{ 433{
434 MEM_TYPE_NON_LISP, 434 MEM_TYPE_NON_LISP,
435 MEM_TYPE_BUFFER,
436 MEM_TYPE_CONS, 435 MEM_TYPE_CONS,
437 MEM_TYPE_STRING, 436 MEM_TYPE_STRING,
438 MEM_TYPE_SYMBOL, 437 MEM_TYPE_SYMBOL,
@@ -3331,12 +3330,10 @@ allocate_pseudovector (int memlen, int lisplen,
3331struct buffer * 3330struct buffer *
3332allocate_buffer (void) 3331allocate_buffer (void)
3333{ 3332{
3334 struct buffer *b = lisp_malloc (sizeof *b, false, MEM_TYPE_BUFFER); 3333 struct buffer *b
3335 3334 = ALLOCATE_PSEUDOVECTOR (struct buffer, cursor_in_non_selected_windows_,
3335 PVEC_BUFFER);
3336 BUFFER_PVEC_INIT (b); 3336 BUFFER_PVEC_INIT (b);
3337 /* Put B on the chain of all buffers including killed ones. */
3338 b->next = all_buffers;
3339 all_buffers = b;
3340 /* Note that the rest fields of B are not initialized. */ 3337 /* Note that the rest fields of B are not initialized. */
3341 return b; 3338 return b;
3342} 3339}
@@ -4596,40 +4593,6 @@ live_vector_p (struct mem_node *m, void *p)
4596 return !NILP (live_vector_holding (m, p)); 4593 return !NILP (live_vector_holding (m, p));
4597} 4594}
4598 4595
4599/* If P is a pointer into a valid buffer object, return the buffer.
4600 Otherwise, return nil. M is a pointer to the mem_block for P.
4601 If IGNORE_KILLED is non-zero, treat killed buffers as invalid. */
4602
4603static Lisp_Object
4604live_buffer_holding (struct mem_node *m, void *p, bool ignore_killed)
4605{
4606 /* P must point into the block, and the buffer must not
4607 have been killed unless ALL-BUFFERS is true. */
4608 if (m->type == MEM_TYPE_BUFFER)
4609 {
4610 struct buffer *b = m->start;
4611 char *cb = m->start;
4612 char *cp = p;
4613 ptrdiff_t offset = cp - cb;
4614 if (0 <= offset && offset < sizeof *b
4615 && !(ignore_killed && NILP (b->name_)))
4616 {
4617 Lisp_Object obj;
4618 XSETBUFFER (obj, b);
4619 return obj;
4620 }
4621 }
4622 return Qnil;
4623}
4624
4625/* If P is a pointer into a live (valid and not killed) buffer object,
4626 return non-zero. */
4627static bool
4628live_buffer_p (struct mem_node *m, void *p)
4629{
4630 return !NILP (live_buffer_holding (m, p, true));
4631}
4632
4633/* Mark OBJ if we can prove it's a Lisp_Object. */ 4596/* Mark OBJ if we can prove it's a Lisp_Object. */
4634 4597
4635static void 4598static void
@@ -4684,8 +4647,7 @@ mark_maybe_object (Lisp_Object obj)
4684 break; 4647 break;
4685 4648
4686 case Lisp_Vectorlike: 4649 case Lisp_Vectorlike:
4687 mark_p = (EQ (obj, live_vector_holding (m, po)) 4650 mark_p = (EQ (obj, live_vector_holding (m, po)));
4688 || EQ (obj, live_buffer_holding (m, po, false)));
4689 break; 4651 break;
4690 4652
4691 default: 4653 default:
@@ -4754,10 +4716,6 @@ mark_maybe_pointer (void *p)
4754 /* Nothing to do; not a pointer to Lisp memory. */ 4716 /* Nothing to do; not a pointer to Lisp memory. */
4755 break; 4717 break;
4756 4718
4757 case MEM_TYPE_BUFFER:
4758 obj = live_buffer_holding (m, p, false);
4759 break;
4760
4761 case MEM_TYPE_CONS: 4719 case MEM_TYPE_CONS:
4762 obj = live_cons_holding (m, p); 4720 obj = live_cons_holding (m, p);
4763 break; 4721 break;
@@ -5157,9 +5115,6 @@ valid_lisp_object_p (Lisp_Object obj)
5157 case MEM_TYPE_SPARE: 5115 case MEM_TYPE_SPARE:
5158 return 0; 5116 return 0;
5159 5117
5160 case MEM_TYPE_BUFFER:
5161 return live_buffer_p (m, p) ? 1 : 2;
5162
5163 case MEM_TYPE_CONS: 5118 case MEM_TYPE_CONS:
5164 return live_cons_p (m, p); 5119 return live_cons_p (m, p);
5165 5120
@@ -5976,7 +5931,7 @@ maybe_garbage_collect (void)
5976void 5931void
5977garbage_collect (void) 5932garbage_collect (void)
5978{ 5933{
5979 struct buffer *nextb; 5934 Lisp_Object tail, buffer;
5980 char stack_top_variable; 5935 char stack_top_variable;
5981 bool message_p; 5936 bool message_p;
5982 ptrdiff_t count = SPECPDL_INDEX (); 5937 ptrdiff_t count = SPECPDL_INDEX ();
@@ -5992,8 +5947,8 @@ garbage_collect (void)
5992 5947
5993 /* Don't keep undo information around forever. 5948 /* Don't keep undo information around forever.
5994 Do this early on, so it is no problem if the user quits. */ 5949 Do this early on, so it is no problem if the user quits. */
5995 FOR_EACH_BUFFER (nextb) 5950 FOR_EACH_LIVE_BUFFER (tail, buffer)
5996 compact_buffer (nextb); 5951 compact_buffer (XBUFFER (buffer));
5997 5952
5998 byte_ct tot_before = (profiler_memory_running 5953 byte_ct tot_before = (profiler_memory_running
5999 ? total_bytes_of_live_objects () 5954 ? total_bytes_of_live_objects ()
@@ -6083,8 +6038,9 @@ garbage_collect (void)
6083 6038
6084 compact_font_caches (); 6039 compact_font_caches ();
6085 6040
6086 FOR_EACH_BUFFER (nextb) 6041 FOR_EACH_LIVE_BUFFER (tail, buffer)
6087 { 6042 {
6043 struct buffer *nextb = XBUFFER (buffer);
6088 if (!EQ (BVAR (nextb, undo_list), Qt)) 6044 if (!EQ (BVAR (nextb, undo_list), Qt))
6089 bset_undo_list (nextb, compact_undo_list (BVAR (nextb, undo_list))); 6045 bset_undo_list (nextb, compact_undo_list (BVAR (nextb, undo_list)));
6090 /* Now that we have stripped the elements that need not be 6046 /* Now that we have stripped the elements that need not be
@@ -6349,7 +6305,12 @@ mark_buffer (struct buffer *buffer)
6349 6305
6350 /* For now, we just don't mark the undo_list. It's done later in 6306 /* For now, we just don't mark the undo_list. It's done later in
6351 a special way just before the sweep phase, and after stripping 6307 a special way just before the sweep phase, and after stripping
6352 some of its elements that are not needed any more. */ 6308 some of its elements that are not needed any more.
6309 Note: this later processing is only done for live buffers, so
6310 for dead buffers, the undo_list should be nil (set by Fkill_buffer),
6311 but just to be on the safe side, we mark it here. */
6312 if (!BUFFER_LIVE_P (buffer))
6313 mark_object (BVAR (buffer, undo_list));
6353 6314
6354 mark_overlay (buffer->overlays_before); 6315 mark_overlay (buffer->overlays_before);
6355 mark_overlay (buffer->overlays_after); 6316 mark_overlay (buffer->overlays_after);
@@ -6613,23 +6574,12 @@ mark_object (Lisp_Object arg)
6613 = PSEUDOVECTOR_TYPE (ptr); 6574 = PSEUDOVECTOR_TYPE (ptr);
6614 6575
6615 if (pvectype != PVEC_SUBR && 6576 if (pvectype != PVEC_SUBR &&
6616 pvectype != PVEC_BUFFER &&
6617 !main_thread_p (po)) 6577 !main_thread_p (po))
6618 CHECK_LIVE (live_vector_p); 6578 CHECK_LIVE (live_vector_p);
6619 6579
6620 switch (pvectype) 6580 switch (pvectype)
6621 { 6581 {
6622 case PVEC_BUFFER: 6582 case PVEC_BUFFER:
6623#if GC_CHECK_MARKED_OBJECTS
6624 {
6625 struct buffer *b;
6626 FOR_EACH_BUFFER (b)
6627 if (b == po)
6628 break;
6629 if (b == NULL)
6630 emacs_abort ();
6631 }
6632#endif /* GC_CHECK_MARKED_OBJECTS */
6633 mark_buffer ((struct buffer *) ptr); 6583 mark_buffer ((struct buffer *) ptr);
6634 break; 6584 break;
6635 6585
@@ -7108,25 +7058,17 @@ NO_INLINE /* For better stack traces */
7108static void 7058static void
7109sweep_buffers (void) 7059sweep_buffers (void)
7110{ 7060{
7111 struct buffer *buffer, **bprev = &all_buffers; 7061 Lisp_Object tail, buf;
7112 7062
7113 gcstat.total_buffers = 0; 7063 gcstat.total_buffers = 0;
7114 for (buffer = all_buffers; buffer; buffer = *bprev) 7064 FOR_EACH_LIVE_BUFFER (tail, buf)
7115 if (!vectorlike_marked_p (&buffer->header)) 7065 {
7116 { 7066 struct buffer *buffer = XBUFFER (buf);
7117 *bprev = buffer->next; 7067 /* Do not use buffer_(set|get)_intervals here. */
7118 lisp_free (buffer); 7068 buffer->text->intervals = balance_intervals (buffer->text->intervals);
7119 } 7069 unchain_dead_markers (buffer);
7120 else 7070 gcstat.total_buffers++;
7121 { 7071 }
7122 if (!pdumper_object_p (buffer))
7123 XUNMARK_VECTOR (buffer);
7124 /* Do not use buffer_(set|get)_intervals here. */
7125 buffer->text->intervals = balance_intervals (buffer->text->intervals);
7126 unchain_dead_markers (buffer);
7127 gcstat.total_buffers++;
7128 bprev = &buffer->next;
7129 }
7130} 7072}
7131 7073
7132/* Sweep: find all structures not marked, and free them. */ 7074/* Sweep: find all structures not marked, and free them. */