2866 |
|
|
2867 |
union Lisp_Misc *marker_free_list; |
union Lisp_Misc *marker_free_list; |
2868 |
|
|
|
/* Marker blocks which should be freed at end of GC. */ |
|
|
|
|
|
struct marker_block *marker_blocks_pending_free; |
|
|
|
|
2869 |
/* Total number of marker blocks now in use. */ |
/* Total number of marker blocks now in use. */ |
2870 |
|
|
2871 |
int n_marker_blocks; |
int n_marker_blocks; |
2876 |
marker_block = NULL; |
marker_block = NULL; |
2877 |
marker_block_index = MARKER_BLOCK_SIZE; |
marker_block_index = MARKER_BLOCK_SIZE; |
2878 |
marker_free_list = 0; |
marker_free_list = 0; |
|
marker_blocks_pending_free = 0; |
|
2879 |
n_marker_blocks = 0; |
n_marker_blocks = 0; |
2880 |
} |
} |
2881 |
|
|
4454 |
} |
} |
4455 |
#endif |
#endif |
4456 |
|
|
4457 |
gc_sweep (); |
/* Everything is now marked, except for the things that require special |
4458 |
|
finalization, i.e. the undo_list. |
4459 |
/* Look thru every buffer's undo list for elements that used to |
Look thru every buffer's undo list |
4460 |
contain update markers that were changed to Lisp_Misc_Free |
for elements that update markers that were not marked, |
4461 |
objects and delete them. This may leave a few cons cells |
and delete them. */ |
|
unchained, but we will get those on the next sweep. */ |
|
4462 |
{ |
{ |
4463 |
register struct buffer *nextb = all_buffers; |
register struct buffer *nextb = all_buffers; |
4464 |
|
|
4465 |
while (nextb) |
while (nextb) |
4466 |
{ |
{ |
4467 |
/* If a buffer's undo list is Qt, that means that undo is |
/* If a buffer's undo list is Qt, that means that undo is |
4468 |
turned off in that buffer. */ |
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. */ |
4471 |
if (! EQ (nextb->undo_list, Qt)) |
if (! EQ (nextb->undo_list, Qt)) |
4472 |
{ |
{ |
4473 |
Lisp_Object tail, prev, elt, car; |
Lisp_Object tail, prev; |
4474 |
tail = nextb->undo_list; |
tail = nextb->undo_list; |
4475 |
prev = Qnil; |
prev = Qnil; |
4476 |
while (CONSP (tail)) |
while (CONSP (tail)) |
4477 |
{ |
{ |
4478 |
if ((elt = XCAR (tail), GC_CONSP (elt)) |
if (GC_CONSP (XCAR (tail)) |
4479 |
&& (car = XCAR (elt), GC_MISCP (car)) |
&& GC_MARKERP (XCAR (XCAR (tail))) |
4480 |
&& XMISCTYPE (car) == Lisp_Misc_Free) |
&& !XMARKER (XCAR (XCAR (tail)))->gcmarkbit) |
4481 |
{ |
{ |
|
Lisp_Object cdr = XCDR (tail); |
|
|
/* Do not use free_cons here, as we don't know if |
|
|
anybody else has a pointer to these conses. */ |
|
|
XSETCAR (elt, Qnil); |
|
|
XSETCDR (elt, Qnil); |
|
|
XSETCAR (tail, Qnil); |
|
|
XSETCDR (tail, Qnil); |
|
4482 |
if (NILP (prev)) |
if (NILP (prev)) |
4483 |
nextb->undo_list = tail = cdr; |
nextb->undo_list = tail = XCDR (tail); |
4484 |
else |
else |
4485 |
{ |
{ |
4486 |
tail = cdr; |
tail = XCDR (tail); |
4487 |
XSETCDR (prev, tail); |
XSETCDR (prev, tail); |
4488 |
} |
} |
4489 |
} |
} |
4494 |
} |
} |
4495 |
} |
} |
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); |
4500 |
|
|
4501 |
nextb = nextb->next; |
nextb = nextb->next; |
4502 |
} |
} |
4503 |
} |
} |
4504 |
|
|
4505 |
/* Undo lists have been cleaned up, so we can free marker blocks now. */ |
gc_sweep (); |
|
|
|
|
{ |
|
|
struct marker_block *mblk; |
|
|
|
|
|
while ((mblk = marker_blocks_pending_free) != 0) |
|
|
{ |
|
|
marker_blocks_pending_free = mblk->next; |
|
|
lisp_free (mblk); |
|
|
} |
|
|
} |
|
4506 |
|
|
4507 |
/* Clear the mark bits that we set in certain root slots. */ |
/* Clear the mark bits that we set in certain root slots. */ |
4508 |
|
|
5070 |
|
|
5071 |
MARK_INTERVAL_TREE (BUF_INTERVALS (buffer)); |
MARK_INTERVAL_TREE (BUF_INTERVALS (buffer)); |
5072 |
|
|
5073 |
if (CONSP (buffer->undo_list)) |
/* For now, we just don't mark the undo_list. It's done later in |
5074 |
{ |
a special way just before the sweep phase, and after stripping |
5075 |
Lisp_Object tail; |
some of its elements that are not needed any more. */ |
|
tail = buffer->undo_list; |
|
|
|
|
|
/* We mark the undo list specially because |
|
|
its pointers to markers should be weak. */ |
|
|
|
|
|
while (CONSP (tail)) |
|
|
{ |
|
|
register struct Lisp_Cons *ptr = XCONS (tail); |
|
|
|
|
|
if (CONS_MARKED_P (ptr)) |
|
|
break; |
|
|
CONS_MARK (ptr); |
|
|
if (GC_CONSP (ptr->car) |
|
|
&& !CONS_MARKED_P (XCONS (ptr->car)) |
|
|
&& GC_MARKERP (XCAR (ptr->car))) |
|
|
{ |
|
|
CONS_MARK (XCONS (ptr->car)); |
|
|
mark_object (XCDR (ptr->car)); |
|
|
} |
|
|
else |
|
|
mark_object (ptr->car); |
|
|
|
|
|
if (CONSP (ptr->cdr)) |
|
|
tail = ptr->cdr; |
|
|
else |
|
|
break; |
|
|
} |
|
|
|
|
|
mark_object (XCDR (tail)); |
|
|
} |
|
|
else |
|
|
mark_object (buffer->undo_list); |
|
5076 |
|
|
5077 |
if (buffer->overlays_before) |
if (buffer->overlays_before) |
5078 |
{ |
{ |
5152 |
static void |
static void |
5153 |
gc_sweep () |
gc_sweep () |
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 |
|
|
5165 |
/* Put all unmarked conses on free list */ |
/* Put all unmarked conses on free list */ |
5166 |
{ |
{ |
5167 |
register struct cons_block *cblk; |
register struct cons_block *cblk; |
5212 |
total_free_conses = num_free; |
total_free_conses = num_free; |
5213 |
} |
} |
5214 |
|
|
|
/* Remove or mark entries in weak hash tables. |
|
|
This must be done before any object is unmarked. */ |
|
|
sweep_weak_hash_tables (); |
|
|
|
|
|
sweep_strings (); |
|
|
#ifdef GC_CHECK_STRING_BYTES |
|
|
if (!noninteractive) |
|
|
check_string_bytes (1); |
|
|
#endif |
|
|
|
|
5215 |
/* Put all unmarked floats on free list */ |
/* Put all unmarked floats on free list */ |
5216 |
{ |
{ |
5217 |
register struct float_block *fblk; |
register struct float_block *fblk; |
5380 |
register int num_free = 0, num_used = 0; |
register int num_free = 0, num_used = 0; |
5381 |
|
|
5382 |
marker_free_list = 0; |
marker_free_list = 0; |
|
marker_blocks_pending_free = 0; |
|
5383 |
|
|
5384 |
for (mblk = marker_block; mblk; mblk = *mprev) |
for (mblk = marker_block; mblk; mblk = *mprev) |
5385 |
{ |
{ |
5415 |
*mprev = mblk->next; |
*mprev = mblk->next; |
5416 |
/* Unhook from the free list. */ |
/* Unhook from the free list. */ |
5417 |
marker_free_list = mblk->markers[0].u_free.chain; |
marker_free_list = mblk->markers[0].u_free.chain; |
5418 |
|
lisp_free (mblk); |
5419 |
n_marker_blocks--; |
n_marker_blocks--; |
|
|
|
|
/* It is not safe to free the marker block at this stage, |
|
|
since there may still be pointers to these markers from |
|
|
a buffer's undo list. KFS 2004-05-25. */ |
|
|
mblk->next = marker_blocks_pending_free; |
|
|
marker_blocks_pending_free = mblk; |
|
5420 |
} |
} |
5421 |
else |
else |
5422 |
{ |
{ |