diff options
| author | Stefan Monnier | 2004-05-29 00:00:17 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2004-05-29 00:00:17 +0000 |
| commit | c37adf23e8607a6479a950c7f6b41ca819b7c73c (patch) | |
| tree | 2347a5736c09eeab6d1942fb308245d9f9f32e1f /src/alloc.c | |
| parent | 138c4b3d36b8390387da752825f98d56535f6459 (diff) | |
| download | emacs-c37adf23e8607a6479a950c7f6b41ca819b7c73c.tar.gz emacs-c37adf23e8607a6479a950c7f6b41ca819b7c73c.zip | |
Undo Kim's recent changes and fix the same bug differently.
(marker_blocks_pending_free): Remove.
(Fgarbage_collect): Sweep after cleaning up undo-lists.
Mark the undo lists after claning them up.
Don't free block in marker_blocks_pending_free.
(mark_buffer): Don't mark undo_list.
(gc_sweep): Sweep hash-tables and strings first.
Do free marker blocks that are empty.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 120 |
1 files changed, 32 insertions, 88 deletions
diff --git a/src/alloc.c b/src/alloc.c index 452a1fbb2a1..0a0b25bcb7d 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -2866,10 +2866,6 @@ int marker_block_index; | |||
| 2866 | 2866 | ||
| 2867 | union Lisp_Misc *marker_free_list; | 2867 | union Lisp_Misc *marker_free_list; |
| 2868 | 2868 | ||
| 2869 | /* Marker blocks which should be freed at end of GC. */ | ||
| 2870 | |||
| 2871 | struct marker_block *marker_blocks_pending_free; | ||
| 2872 | |||
| 2873 | /* Total number of marker blocks now in use. */ | 2869 | /* Total number of marker blocks now in use. */ |
| 2874 | 2870 | ||
| 2875 | int n_marker_blocks; | 2871 | int n_marker_blocks; |
| @@ -2880,7 +2876,6 @@ init_marker () | |||
| 2880 | marker_block = NULL; | 2876 | marker_block = NULL; |
| 2881 | marker_block_index = MARKER_BLOCK_SIZE; | 2877 | marker_block_index = MARKER_BLOCK_SIZE; |
| 2882 | marker_free_list = 0; | 2878 | marker_free_list = 0; |
| 2883 | marker_blocks_pending_free = 0; | ||
| 2884 | n_marker_blocks = 0; | 2879 | n_marker_blocks = 0; |
| 2885 | } | 2880 | } |
| 2886 | 2881 | ||
| @@ -4459,42 +4454,36 @@ returns nil, because real GC can't be done. */) | |||
| 4459 | } | 4454 | } |
| 4460 | #endif | 4455 | #endif |
| 4461 | 4456 | ||
| 4462 | gc_sweep (); | 4457 | /* Everything is now marked, except for the things that require special |
| 4463 | 4458 | finalization, i.e. the undo_list. | |
| 4464 | /* Look thru every buffer's undo list for elements that used to | 4459 | Look thru every buffer's undo list |
| 4465 | contain update markers that were changed to Lisp_Misc_Free | 4460 | for elements that update markers that were not marked, |
| 4466 | objects and delete them. This may leave a few cons cells | 4461 | and delete them. */ |
| 4467 | unchained, but we will get those on the next sweep. */ | ||
| 4468 | { | 4462 | { |
| 4469 | register struct buffer *nextb = all_buffers; | 4463 | register struct buffer *nextb = all_buffers; |
| 4470 | 4464 | ||
| 4471 | while (nextb) | 4465 | while (nextb) |
| 4472 | { | 4466 | { |
| 4473 | /* If a buffer's undo list is Qt, that means that undo is | 4467 | /* If a buffer's undo list is Qt, that means that undo is |
| 4474 | turned off in that buffer. */ | 4468 | turned off in that buffer. Calling truncate_undo_list on |
| 4469 | Qt tends to return NULL, which effectively turns undo back on. | ||
| 4470 | So don't call truncate_undo_list if undo_list is Qt. */ | ||
| 4475 | if (! EQ (nextb->undo_list, Qt)) | 4471 | if (! EQ (nextb->undo_list, Qt)) |
| 4476 | { | 4472 | { |
| 4477 | Lisp_Object tail, prev, elt, car; | 4473 | Lisp_Object tail, prev; |
| 4478 | tail = nextb->undo_list; | 4474 | tail = nextb->undo_list; |
| 4479 | prev = Qnil; | 4475 | prev = Qnil; |
| 4480 | while (CONSP (tail)) | 4476 | while (CONSP (tail)) |
| 4481 | { | 4477 | { |
| 4482 | if ((elt = XCAR (tail), GC_CONSP (elt)) | 4478 | if (GC_CONSP (XCAR (tail)) |
| 4483 | && (car = XCAR (elt), GC_MISCP (car)) | 4479 | && GC_MARKERP (XCAR (XCAR (tail))) |
| 4484 | && XMISCTYPE (car) == Lisp_Misc_Free) | 4480 | && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit) |
| 4485 | { | 4481 | { |
| 4486 | Lisp_Object cdr = XCDR (tail); | ||
| 4487 | /* Do not use free_cons here, as we don't know if | ||
| 4488 | anybody else has a pointer to these conses. */ | ||
| 4489 | XSETCAR (elt, Qnil); | ||
| 4490 | XSETCDR (elt, Qnil); | ||
| 4491 | XSETCAR (tail, Qnil); | ||
| 4492 | XSETCDR (tail, Qnil); | ||
| 4493 | if (NILP (prev)) | 4482 | if (NILP (prev)) |
| 4494 | nextb->undo_list = tail = cdr; | 4483 | nextb->undo_list = tail = XCDR (tail); |
| 4495 | else | 4484 | else |
| 4496 | { | 4485 | { |
| 4497 | tail = cdr; | 4486 | tail = XCDR (tail); |
| 4498 | XSETCDR (prev, tail); | 4487 | XSETCDR (prev, tail); |
| 4499 | } | 4488 | } |
| 4500 | } | 4489 | } |
| @@ -4505,22 +4494,15 @@ returns nil, because real GC can't be done. */) | |||
| 4505 | } | 4494 | } |
| 4506 | } | 4495 | } |
| 4507 | } | 4496 | } |
| 4497 | /* Now that we have stripped the elements that need not be in the | ||
| 4498 | undo_list any more, we can finally mark the list. */ | ||
| 4499 | mark_object (nextb->undo_list); | ||
| 4508 | 4500 | ||
| 4509 | nextb = nextb->next; | 4501 | nextb = nextb->next; |
| 4510 | } | 4502 | } |
| 4511 | } | 4503 | } |
| 4512 | 4504 | ||
| 4513 | /* Undo lists have been cleaned up, so we can free marker blocks now. */ | 4505 | gc_sweep (); |
| 4514 | |||
| 4515 | { | ||
| 4516 | struct marker_block *mblk; | ||
| 4517 | |||
| 4518 | while ((mblk = marker_blocks_pending_free) != 0) | ||
| 4519 | { | ||
| 4520 | marker_blocks_pending_free = mblk->next; | ||
| 4521 | lisp_free (mblk); | ||
| 4522 | } | ||
| 4523 | } | ||
| 4524 | 4506 | ||
| 4525 | /* Clear the mark bits that we set in certain root slots. */ | 4507 | /* Clear the mark bits that we set in certain root slots. */ |
| 4526 | 4508 | ||
| @@ -5088,41 +5070,9 @@ mark_buffer (buf) | |||
| 5088 | 5070 | ||
| 5089 | MARK_INTERVAL_TREE (BUF_INTERVALS (buffer)); | 5071 | MARK_INTERVAL_TREE (BUF_INTERVALS (buffer)); |
| 5090 | 5072 | ||
| 5091 | if (CONSP (buffer->undo_list)) | 5073 | /* For now, we just don't mark the undo_list. It's done later in |
| 5092 | { | 5074 | a special way just before the sweep phase, and after stripping |
| 5093 | Lisp_Object tail; | 5075 | some of its elements that are not needed any more. */ |
| 5094 | tail = buffer->undo_list; | ||
| 5095 | |||
| 5096 | /* We mark the undo list specially because | ||
| 5097 | its pointers to markers should be weak. */ | ||
| 5098 | |||
| 5099 | while (CONSP (tail)) | ||
| 5100 | { | ||
| 5101 | register struct Lisp_Cons *ptr = XCONS (tail); | ||
| 5102 | |||
| 5103 | if (CONS_MARKED_P (ptr)) | ||
| 5104 | break; | ||
| 5105 | CONS_MARK (ptr); | ||
| 5106 | if (GC_CONSP (ptr->car) | ||
| 5107 | && !CONS_MARKED_P (XCONS (ptr->car)) | ||
| 5108 | && GC_MARKERP (XCAR (ptr->car))) | ||
| 5109 | { | ||
| 5110 | CONS_MARK (XCONS (ptr->car)); | ||
| 5111 | mark_object (XCDR (ptr->car)); | ||
| 5112 | } | ||
| 5113 | else | ||
| 5114 | mark_object (ptr->car); | ||
| 5115 | |||
| 5116 | if (CONSP (ptr->cdr)) | ||
| 5117 | tail = ptr->cdr; | ||
| 5118 | else | ||
| 5119 | break; | ||
| 5120 | } | ||
| 5121 | |||
| 5122 | mark_object (XCDR (tail)); | ||
| 5123 | } | ||
| 5124 | else | ||
| 5125 | mark_object (buffer->undo_list); | ||
| 5126 | 5076 | ||
| 5127 | if (buffer->overlays_before) | 5077 | if (buffer->overlays_before) |
| 5128 | { | 5078 | { |
| @@ -5202,6 +5152,16 @@ survives_gc_p (obj) | |||
| 5202 | static void | 5152 | static void |
| 5203 | gc_sweep () | 5153 | gc_sweep () |
| 5204 | { | 5154 | { |
| 5155 | /* Remove or mark entries in weak hash tables. | ||
| 5156 | This must be done before any object is unmarked. */ | ||
| 5157 | sweep_weak_hash_tables (); | ||
| 5158 | |||
| 5159 | sweep_strings (); | ||
| 5160 | #ifdef GC_CHECK_STRING_BYTES | ||
| 5161 | if (!noninteractive) | ||
| 5162 | check_string_bytes (1); | ||
| 5163 | #endif | ||
| 5164 | |||
| 5205 | /* Put all unmarked conses on free list */ | 5165 | /* Put all unmarked conses on free list */ |
| 5206 | { | 5166 | { |
| 5207 | register struct cons_block *cblk; | 5167 | register struct cons_block *cblk; |
| @@ -5252,16 +5212,6 @@ gc_sweep () | |||
| 5252 | total_free_conses = num_free; | 5212 | total_free_conses = num_free; |
| 5253 | } | 5213 | } |
| 5254 | 5214 | ||
| 5255 | /* Remove or mark entries in weak hash tables. | ||
| 5256 | This must be done before any object is unmarked. */ | ||
| 5257 | sweep_weak_hash_tables (); | ||
| 5258 | |||
| 5259 | sweep_strings (); | ||
| 5260 | #ifdef GC_CHECK_STRING_BYTES | ||
| 5261 | if (!noninteractive) | ||
| 5262 | check_string_bytes (1); | ||
| 5263 | #endif | ||
| 5264 | |||
| 5265 | /* Put all unmarked floats on free list */ | 5215 | /* Put all unmarked floats on free list */ |
| 5266 | { | 5216 | { |
| 5267 | register struct float_block *fblk; | 5217 | register struct float_block *fblk; |
| @@ -5430,7 +5380,6 @@ gc_sweep () | |||
| 5430 | register int num_free = 0, num_used = 0; | 5380 | register int num_free = 0, num_used = 0; |
| 5431 | 5381 | ||
| 5432 | marker_free_list = 0; | 5382 | marker_free_list = 0; |
| 5433 | marker_blocks_pending_free = 0; | ||
| 5434 | 5383 | ||
| 5435 | for (mblk = marker_block; mblk; mblk = *mprev) | 5384 | for (mblk = marker_block; mblk; mblk = *mprev) |
| 5436 | { | 5385 | { |
| @@ -5466,13 +5415,8 @@ gc_sweep () | |||
| 5466 | *mprev = mblk->next; | 5415 | *mprev = mblk->next; |
| 5467 | /* Unhook from the free list. */ | 5416 | /* Unhook from the free list. */ |
| 5468 | marker_free_list = mblk->markers[0].u_free.chain; | 5417 | marker_free_list = mblk->markers[0].u_free.chain; |
| 5418 | lisp_free (mblk); | ||
| 5469 | n_marker_blocks--; | 5419 | n_marker_blocks--; |
| 5470 | |||
| 5471 | /* It is not safe to free the marker block at this stage, | ||
| 5472 | since there may still be pointers to these markers from | ||
| 5473 | a buffer's undo list. KFS 2004-05-25. */ | ||
| 5474 | mblk->next = marker_blocks_pending_free; | ||
| 5475 | marker_blocks_pending_free = mblk; | ||
| 5476 | } | 5420 | } |
| 5477 | else | 5421 | else |
| 5478 | { | 5422 | { |