Mercurial > emacs
comparison src/alloc.c @ 55720:1a56baecf37d
(struct backtrace): Add debug_on_exit member.
(Fgarbage_collect): Clear out buffer undo_list markers after gc_sweep.
Identify those markers as Lisp_Misc_Free objects. Clear car and cdr of
the removed cons cells.
(mark_object): Undo previous change - disallow Lisp_Misc_Free objects.
(gc_sweep): Clear cons_blocks before sweeping strings, so we don't have
any cons cells pointing to unallocated stings.
Do not lisp_free any marker blocks, as there may still be pointers
to them from buffer undo lists at this stage of GC.
| author | Kim F. Storm <storm@cua.dk> |
|---|---|
| date | Fri, 21 May 2004 23:36:10 +0000 |
| parents | 57f4a242e8f4 |
| children | 1c3b8ce97c63 |
comparison
equal
deleted
inserted
replaced
| 55719:91bed9994bc1 | 55720:1a56baecf37d |
|---|---|
| 2331 #if GC_MARK_STACK | 2331 #if GC_MARK_STACK |
| 2332 ptr->car = Vdead; | 2332 ptr->car = Vdead; |
| 2333 #endif | 2333 #endif |
| 2334 cons_free_list = ptr; | 2334 cons_free_list = ptr; |
| 2335 } | 2335 } |
| 2336 | |
| 2337 | 2336 |
| 2338 DEFUN ("cons", Fcons, Scons, 2, 2, 0, | 2337 DEFUN ("cons", Fcons, Scons, 2, 2, 0, |
| 2339 doc: /* Create a new cons, give it CAR and CDR as components, and return it. */) | 2338 doc: /* Create a new cons, give it CAR and CDR as components, and return it. */) |
| 2340 (car, cdr) | 2339 (car, cdr) |
| 2341 Lisp_Object car, cdr; | 2340 Lisp_Object car, cdr; |
| 4284 Lisp_Object *args; /* Points to vector of args. */ | 4283 Lisp_Object *args; /* Points to vector of args. */ |
| 4285 int nargs; /* Length of vector. */ | 4284 int nargs; /* Length of vector. */ |
| 4286 /* If nargs is UNEVALLED, args points to slot holding list of | 4285 /* If nargs is UNEVALLED, args points to slot holding list of |
| 4287 unevalled args. */ | 4286 unevalled args. */ |
| 4288 char evalargs; | 4287 char evalargs; |
| 4288 /* Nonzero means call value of debugger when done with this operation. */ | |
| 4289 char debug_on_exit; | |
| 4289 }; | 4290 }; |
| 4290 | 4291 |
| 4291 | 4292 |
| 4292 | 4293 |
| 4293 /*********************************************************************** | 4294 /*********************************************************************** |
| 4474 extern void xg_mark_data (); | 4475 extern void xg_mark_data (); |
| 4475 xg_mark_data (); | 4476 xg_mark_data (); |
| 4476 } | 4477 } |
| 4477 #endif | 4478 #endif |
| 4478 | 4479 |
| 4479 /* Look thru every buffer's undo list | 4480 gc_sweep (); |
| 4480 for elements that update markers that were not marked, | 4481 |
| 4481 and delete them. */ | 4482 /* Look thru every buffer's undo list for elements that used to |
| 4483 contain update markers that were changed to Lisp_Misc_Free | |
| 4484 objects and delete them. This may leave a few cons cells | |
| 4485 unchained, but we will get those on the next sweep. */ | |
| 4482 { | 4486 { |
| 4483 register struct buffer *nextb = all_buffers; | 4487 register struct buffer *nextb = all_buffers; |
| 4484 | 4488 |
| 4485 while (nextb) | 4489 while (nextb) |
| 4486 { | 4490 { |
| 4487 /* If a buffer's undo list is Qt, that means that undo is | 4491 /* If a buffer's undo list is Qt, that means that undo is |
| 4488 turned off in that buffer. Calling truncate_undo_list on | 4492 turned off in that buffer. */ |
| 4489 Qt tends to return NULL, which effectively turns undo back on. | |
| 4490 So don't call truncate_undo_list if undo_list is Qt. */ | |
| 4491 if (! EQ (nextb->undo_list, Qt)) | 4493 if (! EQ (nextb->undo_list, Qt)) |
| 4492 { | 4494 { |
| 4493 Lisp_Object tail, prev; | 4495 Lisp_Object tail, prev, elt, car; |
| 4494 tail = nextb->undo_list; | 4496 tail = nextb->undo_list; |
| 4495 prev = Qnil; | 4497 prev = Qnil; |
| 4496 while (CONSP (tail)) | 4498 while (CONSP (tail)) |
| 4497 { | 4499 { |
| 4498 if (GC_CONSP (XCAR (tail)) | 4500 if ((elt = XCAR (tail), GC_CONSP (elt)) |
| 4499 && GC_MARKERP (XCAR (XCAR (tail))) | 4501 && (car = XCAR (elt), GC_MISCP (car)) |
| 4500 && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit) | 4502 && XMISCTYPE (car) == Lisp_Misc_Free) |
| 4501 { | 4503 { |
| 4504 Lisp_Object cdr = XCDR (tail); | |
| 4505 /* Do not use free_cons here, as we don't know if | |
| 4506 anybody else has a pointer to these conses. */ | |
| 4507 XSETCAR (elt, Qnil); | |
| 4508 XSETCDR (elt, Qnil); | |
| 4509 XSETCAR (tail, Qnil); | |
| 4510 XSETCDR (tail, Qnil); | |
| 4502 if (NILP (prev)) | 4511 if (NILP (prev)) |
| 4503 nextb->undo_list = tail = XCDR (tail); | 4512 nextb->undo_list = tail = cdr; |
| 4504 else | 4513 else |
| 4505 { | 4514 { |
| 4506 tail = XCDR (tail); | 4515 tail = cdr; |
| 4507 XSETCDR (prev, tail); | 4516 XSETCDR (prev, tail); |
| 4508 } | 4517 } |
| 4509 } | 4518 } |
| 4510 else | 4519 else |
| 4511 { | 4520 { |
| 4516 } | 4525 } |
| 4517 | 4526 |
| 4518 nextb = nextb->next; | 4527 nextb = nextb->next; |
| 4519 } | 4528 } |
| 4520 } | 4529 } |
| 4521 | |
| 4522 gc_sweep (); | |
| 4523 | 4530 |
| 4524 /* Clear the mark bits that we set in certain root slots. */ | 4531 /* Clear the mark bits that we set in certain root slots. */ |
| 4525 | 4532 |
| 4526 unmark_byte_stack (); | 4533 unmark_byte_stack (); |
| 4527 VECTOR_UNMARK (&buffer_defaults); | 4534 VECTOR_UNMARK (&buffer_defaults); |
| 4974 } | 4981 } |
| 4975 } | 4982 } |
| 4976 break; | 4983 break; |
| 4977 | 4984 |
| 4978 case Lisp_Misc: | 4985 case Lisp_Misc: |
| 4979 if (XMISCTYPE (obj) == Lisp_Misc_Free) | |
| 4980 { | |
| 4981 /* This is (probably) a freed marker which may still exist on | |
| 4982 a buffer undo list, so accept it here, as check below will | |
| 4983 fail (not live). KFS 2004-05-17 */ | |
| 4984 XMARKER (obj)->gcmarkbit = 1; | |
| 4985 break; | |
| 4986 } | |
| 4987 CHECK_ALLOCATED_AND_LIVE (live_misc_p); | 4986 CHECK_ALLOCATED_AND_LIVE (live_misc_p); |
| 4988 if (XMARKER (obj)->gcmarkbit) | 4987 if (XMARKER (obj)->gcmarkbit) |
| 4989 break; | 4988 break; |
| 4990 XMARKER (obj)->gcmarkbit = 1; | 4989 XMARKER (obj)->gcmarkbit = 1; |
| 4991 switch (XMISCTYPE (obj)) | 4990 switch (XMISCTYPE (obj)) |
| 5207 /* Sweep: find all structures not marked, and free them. */ | 5206 /* Sweep: find all structures not marked, and free them. */ |
| 5208 | 5207 |
| 5209 static void | 5208 static void |
| 5210 gc_sweep () | 5209 gc_sweep () |
| 5211 { | 5210 { |
| 5212 /* Remove or mark entries in weak hash tables. | |
| 5213 This must be done before any object is unmarked. */ | |
| 5214 sweep_weak_hash_tables (); | |
| 5215 | |
| 5216 sweep_strings (); | |
| 5217 #ifdef GC_CHECK_STRING_BYTES | |
| 5218 if (!noninteractive) | |
| 5219 check_string_bytes (1); | |
| 5220 #endif | |
| 5221 | |
| 5222 /* Put all unmarked conses on free list */ | 5211 /* Put all unmarked conses on free list */ |
| 5223 { | 5212 { |
| 5224 register struct cons_block *cblk; | 5213 register struct cons_block *cblk; |
| 5225 struct cons_block **cprev = &cons_block; | 5214 struct cons_block **cprev = &cons_block; |
| 5226 register int lim = cons_block_index; | 5215 register int lim = cons_block_index; |
| 5266 } | 5255 } |
| 5267 } | 5256 } |
| 5268 total_conses = num_used; | 5257 total_conses = num_used; |
| 5269 total_free_conses = num_free; | 5258 total_free_conses = num_free; |
| 5270 } | 5259 } |
| 5260 | |
| 5261 /* Remove or mark entries in weak hash tables. | |
| 5262 This must be done before any object is unmarked. */ | |
| 5263 sweep_weak_hash_tables (); | |
| 5264 | |
| 5265 sweep_strings (); | |
| 5266 #ifdef GC_CHECK_STRING_BYTES | |
| 5267 if (!noninteractive) | |
| 5268 check_string_bytes (1); | |
| 5269 #endif | |
| 5271 | 5270 |
| 5272 /* Put all unmarked floats on free list */ | 5271 /* Put all unmarked floats on free list */ |
| 5273 { | 5272 { |
| 5274 register struct float_block *fblk; | 5273 register struct float_block *fblk; |
| 5275 struct float_block **fprev = &float_block; | 5274 struct float_block **fprev = &float_block; |
| 5465 } | 5464 } |
| 5466 lim = MARKER_BLOCK_SIZE; | 5465 lim = MARKER_BLOCK_SIZE; |
| 5467 /* If this block contains only free markers and we have already | 5466 /* If this block contains only free markers and we have already |
| 5468 seen more than two blocks worth of free markers then deallocate | 5467 seen more than two blocks worth of free markers then deallocate |
| 5469 this block. */ | 5468 this block. */ |
| 5469 #if 0 | |
| 5470 /* There may still be pointers to these markers from a buffer's | |
| 5471 undo list, so don't free them. KFS 2004-05-21 / | |
| 5470 if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE) | 5472 if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE) |
| 5471 { | 5473 { |
| 5472 *mprev = mblk->next; | 5474 *mprev = mblk->next; |
| 5473 /* Unhook from the free list. */ | 5475 /* Unhook from the free list. */ |
| 5474 marker_free_list = mblk->markers[0].u_free.chain; | 5476 marker_free_list = mblk->markers[0].u_free.chain; |
| 5475 lisp_free (mblk); | 5477 lisp_free (mblk); |
| 5476 n_marker_blocks--; | 5478 n_marker_blocks--; |
| 5477 } | 5479 } |
| 5478 else | 5480 else |
| 5481 #endif | |
| 5479 { | 5482 { |
| 5480 num_free += this_free; | 5483 num_free += this_free; |
| 5481 mprev = &mblk->next; | 5484 mprev = &mblk->next; |
| 5482 } | 5485 } |
| 5483 } | 5486 } |
