155 |
|
|
156 |
EMACS_INT undo_limit; |
EMACS_INT undo_limit; |
157 |
EMACS_INT undo_strong_limit; |
EMACS_INT undo_strong_limit; |
158 |
|
EMACS_INT undo_outer_limit; |
159 |
|
|
160 |
/* Number of live and free conses etc. */ |
/* Number of live and free conses etc. */ |
161 |
|
|
257 |
|
|
258 |
static void mark_buffer P_ ((Lisp_Object)); |
static void mark_buffer P_ ((Lisp_Object)); |
259 |
extern void mark_kboards P_ ((void)); |
extern void mark_kboards P_ ((void)); |
260 |
|
extern void mark_backtrace P_ ((void)); |
261 |
static void gc_sweep P_ ((void)); |
static void gc_sweep P_ ((void)); |
262 |
static void mark_glyph_matrix P_ ((struct glyph_matrix *)); |
static void mark_glyph_matrix P_ ((struct glyph_matrix *)); |
263 |
static void mark_face_cache P_ ((struct face_cache *)); |
static void mark_face_cache P_ ((struct face_cache *)); |
755 |
#ifdef HAVE_POSIX_MEMALIGN |
#ifdef HAVE_POSIX_MEMALIGN |
756 |
{ |
{ |
757 |
int err = posix_memalign (&base, BLOCK_ALIGN, ABLOCKS_BYTES); |
int err = posix_memalign (&base, BLOCK_ALIGN, ABLOCKS_BYTES); |
758 |
abase = err ? (base = NULL) : base; |
if (err) |
759 |
|
base = NULL; |
760 |
|
abase = base; |
761 |
} |
} |
762 |
#else |
#else |
763 |
base = malloc (ABLOCKS_BYTES); |
base = malloc (ABLOCKS_BYTES); |
764 |
abase = ALIGN (base, BLOCK_ALIGN); |
abase = ALIGN (base, BLOCK_ALIGN); |
765 |
|
#endif |
766 |
|
|
767 |
if (base == 0) |
if (base == 0) |
768 |
{ |
{ |
769 |
UNBLOCK_INPUT; |
UNBLOCK_INPUT; |
770 |
memory_full (); |
memory_full (); |
771 |
} |
} |
|
#endif |
|
772 |
|
|
773 |
aligned = (base == abase); |
aligned = (base == abase); |
774 |
if (!aligned) |
if (!aligned) |
4283 |
struct catchtag *next; |
struct catchtag *next; |
4284 |
}; |
}; |
4285 |
|
|
|
struct backtrace |
|
|
{ |
|
|
struct backtrace *next; |
|
|
Lisp_Object *function; |
|
|
Lisp_Object *args; /* Points to vector of args. */ |
|
|
int nargs; /* Length of vector. */ |
|
|
/* If nargs is UNEVALLED, args points to slot holding list of |
|
|
unevalled args. */ |
|
|
char evalargs; |
|
|
/* Nonzero means call value of debugger when done with this operation. */ |
|
|
char debug_on_exit; |
|
|
}; |
|
|
|
|
|
|
|
4286 |
|
|
4287 |
/*********************************************************************** |
/*********************************************************************** |
4288 |
Protection from GC |
Protection from GC |
4317 |
register struct specbinding *bind; |
register struct specbinding *bind; |
4318 |
struct catchtag *catch; |
struct catchtag *catch; |
4319 |
struct handler *handler; |
struct handler *handler; |
|
register struct backtrace *backlist; |
|
4320 |
char stack_top_variable; |
char stack_top_variable; |
4321 |
register int i; |
register int i; |
4322 |
int message_p; |
int message_p; |
4385 |
if (! EQ (nextb->undo_list, Qt)) |
if (! EQ (nextb->undo_list, Qt)) |
4386 |
nextb->undo_list |
nextb->undo_list |
4387 |
= truncate_undo_list (nextb->undo_list, undo_limit, |
= truncate_undo_list (nextb->undo_list, undo_limit, |
4388 |
undo_strong_limit); |
undo_strong_limit, undo_outer_limit); |
4389 |
|
|
4390 |
/* Shrink buffer gaps, but skip indirect and dead buffers. */ |
/* Shrink buffer gaps, but skip indirect and dead buffers. */ |
4391 |
if (nextb->base_buffer == 0 && !NILP (nextb->name)) |
if (nextb->base_buffer == 0 && !NILP (nextb->name)) |
4445 |
mark_object (handler->handler); |
mark_object (handler->handler); |
4446 |
mark_object (handler->var); |
mark_object (handler->var); |
4447 |
} |
} |
4448 |
for (backlist = backtrace_list; backlist; backlist = backlist->next) |
mark_backtrace (); |
|
{ |
|
|
mark_object (*backlist->function); |
|
|
|
|
|
if (backlist->nargs == UNEVALLED || backlist->nargs == MANY) |
|
|
i = 0; |
|
|
else |
|
|
i = backlist->nargs - 1; |
|
|
for (; i >= 0; i--) |
|
|
mark_object (backlist->args[i]); |
|
|
} |
|
4449 |
mark_kboards (); |
mark_kboards (); |
4450 |
|
|
4451 |
#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
4459 |
} |
} |
4460 |
#endif |
#endif |
4461 |
|
|
4462 |
gc_sweep (); |
/* Everything is now marked, except for the things that require special |
4463 |
|
finalization, i.e. the undo_list. |
4464 |
/* Look thru every buffer's undo list for elements that used to |
Look thru every buffer's undo list |
4465 |
contain update markers that were changed to Lisp_Misc_Free |
for elements that update markers that were not marked, |
4466 |
objects and delete them. This may leave a few cons cells |
and delete them. */ |
|
unchained, but we will get those on the next sweep. */ |
|
4467 |
{ |
{ |
4468 |
register struct buffer *nextb = all_buffers; |
register struct buffer *nextb = all_buffers; |
4469 |
|
|
4470 |
while (nextb) |
while (nextb) |
4471 |
{ |
{ |
4472 |
/* 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 |
4473 |
turned off in that buffer. */ |
turned off in that buffer. Calling truncate_undo_list on |
4474 |
|
Qt tends to return NULL, which effectively turns undo back on. |
4475 |
|
So don't call truncate_undo_list if undo_list is Qt. */ |
4476 |
if (! EQ (nextb->undo_list, Qt)) |
if (! EQ (nextb->undo_list, Qt)) |
4477 |
{ |
{ |
4478 |
Lisp_Object tail, prev, elt, car; |
Lisp_Object tail, prev; |
4479 |
tail = nextb->undo_list; |
tail = nextb->undo_list; |
4480 |
prev = Qnil; |
prev = Qnil; |
4481 |
while (CONSP (tail)) |
while (CONSP (tail)) |
4482 |
{ |
{ |
4483 |
if ((elt = XCAR (tail), GC_CONSP (elt)) |
if (GC_CONSP (XCAR (tail)) |
4484 |
&& (car = XCAR (elt), GC_MISCP (car)) |
&& GC_MARKERP (XCAR (XCAR (tail))) |
4485 |
&& XMISCTYPE (car) == Lisp_Misc_Free) |
&& !XMARKER (XCAR (XCAR (tail)))->gcmarkbit) |
4486 |
{ |
{ |
|
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); |
|
4487 |
if (NILP (prev)) |
if (NILP (prev)) |
4488 |
nextb->undo_list = tail = cdr; |
nextb->undo_list = tail = XCDR (tail); |
4489 |
else |
else |
4490 |
{ |
{ |
4491 |
tail = cdr; |
tail = XCDR (tail); |
4492 |
XSETCDR (prev, tail); |
XSETCDR (prev, tail); |
4493 |
} |
} |
4494 |
} |
} |
4499 |
} |
} |
4500 |
} |
} |
4501 |
} |
} |
4502 |
|
/* Now that we have stripped the elements that need not be in the |
4503 |
|
undo_list any more, we can finally mark the list. */ |
4504 |
|
mark_object (nextb->undo_list); |
4505 |
|
|
4506 |
nextb = nextb->next; |
nextb = nextb->next; |
4507 |
} |
} |
4508 |
} |
} |
4509 |
|
|
4510 |
|
gc_sweep (); |
4511 |
|
|
4512 |
/* Clear the mark bits that we set in certain root slots. */ |
/* Clear the mark bits that we set in certain root slots. */ |
4513 |
|
|
4514 |
unmark_byte_stack (); |
unmark_byte_stack (); |
5075 |
|
|
5076 |
MARK_INTERVAL_TREE (BUF_INTERVALS (buffer)); |
MARK_INTERVAL_TREE (BUF_INTERVALS (buffer)); |
5077 |
|
|
5078 |
if (CONSP (buffer->undo_list)) |
/* For now, we just don't mark the undo_list. It's done later in |
5079 |
{ |
a special way just before the sweep phase, and after stripping |
5080 |
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); |
|
5081 |
|
|
5082 |
if (buffer->overlays_before) |
if (buffer->overlays_before) |
5083 |
{ |
{ |
5157 |
static void |
static void |
5158 |
gc_sweep () |
gc_sweep () |
5159 |
{ |
{ |
5160 |
|
/* Remove or mark entries in weak hash tables. |
5161 |
|
This must be done before any object is unmarked. */ |
5162 |
|
sweep_weak_hash_tables (); |
5163 |
|
|
5164 |
|
sweep_strings (); |
5165 |
|
#ifdef GC_CHECK_STRING_BYTES |
5166 |
|
if (!noninteractive) |
5167 |
|
check_string_bytes (1); |
5168 |
|
#endif |
5169 |
|
|
5170 |
/* Put all unmarked conses on free list */ |
/* Put all unmarked conses on free list */ |
5171 |
{ |
{ |
5172 |
register struct cons_block *cblk; |
register struct cons_block *cblk; |
5217 |
total_free_conses = num_free; |
total_free_conses = num_free; |
5218 |
} |
} |
5219 |
|
|
|
/* 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 |
|
|
|
|
5220 |
/* Put all unmarked floats on free list */ |
/* Put all unmarked floats on free list */ |
5221 |
{ |
{ |
5222 |
register struct float_block *fblk; |
register struct float_block *fblk; |
5415 |
/* If this block contains only free markers and we have already |
/* If this block contains only free markers and we have already |
5416 |
seen more than two blocks worth of free markers then deallocate |
seen more than two blocks worth of free markers then deallocate |
5417 |
this block. */ |
this block. */ |
|
#if 0 |
|
|
/* There may still be pointers to these markers from a buffer's |
|
|
undo list, so don't free them. KFS 2004-05-21 / |
|
5418 |
if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE) |
if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE) |
5419 |
{ |
{ |
5420 |
*mprev = mblk->next; |
*mprev = mblk->next; |
5424 |
n_marker_blocks--; |
n_marker_blocks--; |
5425 |
} |
} |
5426 |
else |
else |
|
#endif |
|
5427 |
{ |
{ |
5428 |
num_free += this_free; |
num_free += this_free; |
5429 |
mprev = &mblk->next; |
mprev = &mblk->next; |
5671 |
|
|
5672 |
DEFVAR_INT ("undo-strong-limit", &undo_strong_limit, |
DEFVAR_INT ("undo-strong-limit", &undo_strong_limit, |
5673 |
doc: /* Don't keep more than this much size of undo information. |
doc: /* Don't keep more than this much size of undo information. |
5674 |
A command which pushes past this size is itself forgotten. |
A previous command which pushes the undo list past this size |
5675 |
This limit is applied when garbage collection happens. |
is entirely forgotten when GC happens. |
5676 |
The size is counted as the number of bytes occupied, |
The size is counted as the number of bytes occupied, |
5677 |
which includes both saved text and other data. */); |
which includes both saved text and other data. */); |
5678 |
undo_strong_limit = 30000; |
undo_strong_limit = 30000; |
5679 |
|
|
5680 |
|
DEFVAR_INT ("undo-outer-limit", &undo_outer_limit, |
5681 |
|
doc: /* Don't keep more than this much size of undo information. |
5682 |
|
If the current command has produced more than this much undo information, |
5683 |
|
GC discards it. This is a last-ditch limit to prevent memory overflow. |
5684 |
|
The size is counted as the number of bytes occupied, |
5685 |
|
which includes both saved text and other data. */); |
5686 |
|
undo_outer_limit = 300000; |
5687 |
|
|
5688 |
DEFVAR_BOOL ("garbage-collection-messages", &garbage_collection_messages, |
DEFVAR_BOOL ("garbage-collection-messages", &garbage_collection_messages, |
5689 |
doc: /* Non-nil means display messages at start and end of garbage collection. */); |
doc: /* Non-nil means display messages at start and end of garbage collection. */); |
5690 |
garbage_collection_messages = 0; |
garbage_collection_messages = 0; |