comparison src/alloc.c @ 55816:a4fe04f4d9c2

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.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Sat, 29 May 2004 00:00:17 +0000
parents a1bb695e9a0c
children a05a653f63af 62cf3d6337a0
comparison
equal deleted inserted replaced
55815:a6b86fce5676 55816:a4fe04f4d9c2
2864 struct marker_block *marker_block; 2864 struct marker_block *marker_block;
2865 int marker_block_index; 2865 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;
2876 2872
2877 void 2873 void
2878 init_marker () 2874 init_marker ()
2879 { 2875 {
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
2887 /* Return a newly allocated Lisp_Misc object, with no substructure. */ 2882 /* Return a newly allocated Lisp_Misc object, with no substructure. */
2888 2883
4457 extern void xg_mark_data (); 4452 extern void xg_mark_data ();
4458 xg_mark_data (); 4453 xg_mark_data ();
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 }
4501 else 4490 else
4502 { 4491 {
4503 prev = tail; 4492 prev = tail;
4504 tail = XCDR (tail); 4493 tail = XCDR (tail);
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
4527 unmark_byte_stack (); 4509 unmark_byte_stack ();
4528 VECTOR_UNMARK (&buffer_defaults); 4510 VECTOR_UNMARK (&buffer_defaults);
5086 5068
5087 VECTOR_MARK (buffer); 5069 VECTOR_MARK (buffer);
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 {
5129 XSETMISC (tmp, buffer->overlays_before); 5079 XSETMISC (tmp, buffer->overlays_before);
5130 mark_object (tmp); 5080 mark_object (tmp);
5200 /* Sweep: find all structures not marked, and free them. */ 5150 /* Sweep: find all structures not marked, and free them. */
5201 5151
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;
5208 struct cons_block **cprev = &cons_block; 5168 struct cons_block **cprev = &cons_block;
5209 register int lim = cons_block_index; 5169 register int lim = cons_block_index;
5249 } 5209 }
5250 } 5210 }
5251 total_conses = num_used; 5211 total_conses = num_used;
5252 total_free_conses = num_free; 5212 total_free_conses = num_free;
5253 } 5213 }
5254
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 5214
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;
5268 struct float_block **fprev = &float_block; 5218 struct float_block **fprev = &float_block;
5428 struct marker_block **mprev = &marker_block; 5378 struct marker_block **mprev = &marker_block;
5429 register int lim = marker_block_index; 5379 register int lim = marker_block_index;
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 {
5437 register int i; 5386 register int i;
5438 int this_free = 0; 5387 int this_free = 0;
5464 if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE) 5413 if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE)
5465 { 5414 {
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 {
5479 num_free += this_free; 5423 num_free += this_free;
5480 mprev = &mblk->next; 5424 mprev = &mblk->next;