diff options
| author | Stefan Monnier | 2020-03-31 19:45:22 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2020-03-31 19:45:45 -0400 |
| commit | cddf85d256dda8db1fad50e8e766fd7694361b8f (patch) | |
| tree | d6cd89343e879eedf1ca46be759b53388f529096 /src/alloc.c | |
| parent | a477a7b86ba7c59a90b18283cc86769c27de6c7c (diff) | |
| download | emacs-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.c | 106 |
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); | |||
| 432 | enum mem_type | 432 | enum 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, | |||
| 3331 | struct buffer * | 3330 | struct buffer * |
| 3332 | allocate_buffer (void) | 3331 | allocate_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 | |||
| 4603 | static Lisp_Object | ||
| 4604 | live_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. */ | ||
| 4627 | static bool | ||
| 4628 | live_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 | ||
| 4635 | static void | 4598 | static 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) | |||
| 5976 | void | 5931 | void |
| 5977 | garbage_collect (void) | 5932 | garbage_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 */ | |||
| 7108 | static void | 7058 | static void |
| 7109 | sweep_buffers (void) | 7059 | sweep_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. */ |