aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Colascione2014-03-23 14:58:41 -0700
committerDaniel Colascione2014-03-23 14:58:41 -0700
commitb029599f767406002ea892d0bd40420de0a954f6 (patch)
tree2737840e08cbc05981c4598b9525b8c30ce7977a
parent835af7195792e9e736a6acc3ef51b21e23020c2c (diff)
parent577b2ffd2d787506261ed758b086fb4257116dba (diff)
downloademacs-b029599f767406002ea892d0bd40420de0a954f6.tar.gz
emacs-b029599f767406002ea892d0bd40420de0a954f6.zip
Clean up gc_sweep
-rw-r--r--src/ChangeLog13
-rw-r--r--src/alloc.c613
-rw-r--r--src/fns.c1
3 files changed, 330 insertions, 297 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 8b74e921450..d9e99722319 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,16 @@
12014-03-23 Daniel Colascione <dancol@dancol.org>
2
3 Split gc_sweep into discrete functions for legibility and better
4 stack traces.
5
6 * alloc.c (sweep_strings,sweep_vectors): Add NO_INLINE
7 (sweep_vectors): Fix typo in comment.
8 (sweep_conses,sweep_floats,sweep_intervals)
9 (sweep_symbols,sweep_misc,sweep_buffers): New functions.
10 (gc_sweep): Call new functions, to which existing functionality is
11 moved.
12 * fns.c (sweep_weak_hash_tables): Add NO_INLINE.
13
12014-03-23 Juanma Barranquero <lekktu@gmail.com> 142014-03-23 Juanma Barranquero <lekktu@gmail.com>
2 15
3 * w32fns.c (Fw32_shell_execute): Declare `result' only on Cygwin. 16 * w32fns.c (Fw32_shell_execute): Declare `result' only on Cygwin.
diff --git a/src/alloc.c b/src/alloc.c
index 884de3e03e7..e5cd5fed4e3 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -1817,6 +1817,7 @@ allocate_string_data (struct Lisp_String *s,
1817 1817
1818/* Sweep and compact strings. */ 1818/* Sweep and compact strings. */
1819 1819
1820NO_INLINE /* For better stack traces */
1820static void 1821static void
1821sweep_strings (void) 1822sweep_strings (void)
1822{ 1823{
@@ -2933,6 +2934,7 @@ cleanup_vector (struct Lisp_Vector *vector)
2933 2934
2934/* Reclaim space used by unmarked vectors. */ 2935/* Reclaim space used by unmarked vectors. */
2935 2936
2937NO_INLINE /* For better stack traces */
2936static void 2938static void
2937sweep_vectors (void) 2939sweep_vectors (void)
2938{ 2940{
@@ -2987,7 +2989,7 @@ sweep_vectors (void)
2987 2989
2988 if (vector == (struct Lisp_Vector *) block->data 2990 if (vector == (struct Lisp_Vector *) block->data
2989 && !VECTOR_IN_BLOCK (next, block)) 2991 && !VECTOR_IN_BLOCK (next, block))
2990 /* This block should be freed because all of it's 2992 /* This block should be freed because all of its
2991 space was coalesced into the only free vector. */ 2993 space was coalesced into the only free vector. */
2992 free_this_block = 1; 2994 free_this_block = 1;
2993 else 2995 else
@@ -6340,336 +6342,353 @@ survives_gc_p (Lisp_Object obj)
6340 6342
6341 6343
6342 6344
6343/* Sweep: find all structures not marked, and free them. */
6344 6345
6346NO_INLINE /* For better stack traces */
6345static void 6347static void
6346gc_sweep (void) 6348sweep_conses (void)
6347{ 6349{
6348 /* Remove or mark entries in weak hash tables. 6350 register struct cons_block *cblk;
6349 This must be done before any object is unmarked. */ 6351 struct cons_block **cprev = &cons_block;
6350 sweep_weak_hash_tables (); 6352 register int lim = cons_block_index;
6351 6353 EMACS_INT num_free = 0, num_used = 0;
6352 sweep_strings ();
6353 check_string_bytes (!noninteractive);
6354
6355 /* Put all unmarked conses on free list. */
6356 {
6357 register struct cons_block *cblk;
6358 struct cons_block **cprev = &cons_block;
6359 register int lim = cons_block_index;
6360 EMACS_INT num_free = 0, num_used = 0;
6361 6354
6362 cons_free_list = 0; 6355 cons_free_list = 0;
6363 6356
6364 for (cblk = cons_block; cblk; cblk = *cprev) 6357 for (cblk = cons_block; cblk; cblk = *cprev)
6365 { 6358 {
6366 register int i = 0; 6359 register int i = 0;
6367 int this_free = 0; 6360 int this_free = 0;
6368 int ilim = (lim + BITS_PER_INT - 1) / BITS_PER_INT; 6361 int ilim = (lim + BITS_PER_INT - 1) / BITS_PER_INT;
6369 6362
6370 /* Scan the mark bits an int at a time. */ 6363 /* Scan the mark bits an int at a time. */
6371 for (i = 0; i < ilim; i++) 6364 for (i = 0; i < ilim; i++)
6372 { 6365 {
6373 if (cblk->gcmarkbits[i] == -1) 6366 if (cblk->gcmarkbits[i] == -1)
6374 { 6367 {
6375 /* Fast path - all cons cells for this int are marked. */ 6368 /* Fast path - all cons cells for this int are marked. */
6376 cblk->gcmarkbits[i] = 0; 6369 cblk->gcmarkbits[i] = 0;
6377 num_used += BITS_PER_INT; 6370 num_used += BITS_PER_INT;
6378 } 6371 }
6379 else 6372 else
6380 { 6373 {
6381 /* Some cons cells for this int are not marked. 6374 /* Some cons cells for this int are not marked.
6382 Find which ones, and free them. */ 6375 Find which ones, and free them. */
6383 int start, pos, stop; 6376 int start, pos, stop;
6384 6377
6385 start = i * BITS_PER_INT; 6378 start = i * BITS_PER_INT;
6386 stop = lim - start; 6379 stop = lim - start;
6387 if (stop > BITS_PER_INT) 6380 if (stop > BITS_PER_INT)
6388 stop = BITS_PER_INT; 6381 stop = BITS_PER_INT;
6389 stop += start; 6382 stop += start;
6390 6383
6391 for (pos = start; pos < stop; pos++) 6384 for (pos = start; pos < stop; pos++)
6392 { 6385 {
6393 if (!CONS_MARKED_P (&cblk->conses[pos])) 6386 if (!CONS_MARKED_P (&cblk->conses[pos]))
6394 { 6387 {
6395 this_free++; 6388 this_free++;
6396 cblk->conses[pos].u.chain = cons_free_list; 6389 cblk->conses[pos].u.chain = cons_free_list;
6397 cons_free_list = &cblk->conses[pos]; 6390 cons_free_list = &cblk->conses[pos];
6398#if GC_MARK_STACK 6391#if GC_MARK_STACK
6399 cons_free_list->car = Vdead; 6392 cons_free_list->car = Vdead;
6400#endif 6393#endif
6401 } 6394 }
6402 else 6395 else
6403 { 6396 {
6404 num_used++; 6397 num_used++;
6405 CONS_UNMARK (&cblk->conses[pos]); 6398 CONS_UNMARK (&cblk->conses[pos]);
6406 } 6399 }
6407 } 6400 }
6408 } 6401 }
6409 } 6402 }
6410
6411 lim = CONS_BLOCK_SIZE;
6412 /* If this block contains only free conses and we have already
6413 seen more than two blocks worth of free conses then deallocate
6414 this block. */
6415 if (this_free == CONS_BLOCK_SIZE && num_free > CONS_BLOCK_SIZE)
6416 {
6417 *cprev = cblk->next;
6418 /* Unhook from the free list. */
6419 cons_free_list = cblk->conses[0].u.chain;
6420 lisp_align_free (cblk);
6421 }
6422 else
6423 {
6424 num_free += this_free;
6425 cprev = &cblk->next;
6426 }
6427 }
6428 total_conses = num_used;
6429 total_free_conses = num_free;
6430 }
6431 6403
6432 /* Put all unmarked floats on free list. */ 6404 lim = CONS_BLOCK_SIZE;
6433 { 6405 /* If this block contains only free conses and we have already
6434 register struct float_block *fblk; 6406 seen more than two blocks worth of free conses then deallocate
6435 struct float_block **fprev = &float_block; 6407 this block. */
6436 register int lim = float_block_index; 6408 if (this_free == CONS_BLOCK_SIZE && num_free > CONS_BLOCK_SIZE)
6437 EMACS_INT num_free = 0, num_used = 0; 6409 {
6410 *cprev = cblk->next;
6411 /* Unhook from the free list. */
6412 cons_free_list = cblk->conses[0].u.chain;
6413 lisp_align_free (cblk);
6414 }
6415 else
6416 {
6417 num_free += this_free;
6418 cprev = &cblk->next;
6419 }
6420 }
6421 total_conses = num_used;
6422 total_free_conses = num_free;
6423}
6438 6424
6439 float_free_list = 0; 6425NO_INLINE /* For better stack traces */
6426static void
6427sweep_floats (void)
6428{
6429 register struct float_block *fblk;
6430 struct float_block **fprev = &float_block;
6431 register int lim = float_block_index;
6432 EMACS_INT num_free = 0, num_used = 0;
6440 6433
6441 for (fblk = float_block; fblk; fblk = *fprev) 6434 float_free_list = 0;
6442 {
6443 register int i;
6444 int this_free = 0;
6445 for (i = 0; i < lim; i++)
6446 if (!FLOAT_MARKED_P (&fblk->floats[i]))
6447 {
6448 this_free++;
6449 fblk->floats[i].u.chain = float_free_list;
6450 float_free_list = &fblk->floats[i];
6451 }
6452 else
6453 {
6454 num_used++;
6455 FLOAT_UNMARK (&fblk->floats[i]);
6456 }
6457 lim = FLOAT_BLOCK_SIZE;
6458 /* If this block contains only free floats and we have already
6459 seen more than two blocks worth of free floats then deallocate
6460 this block. */
6461 if (this_free == FLOAT_BLOCK_SIZE && num_free > FLOAT_BLOCK_SIZE)
6462 {
6463 *fprev = fblk->next;
6464 /* Unhook from the free list. */
6465 float_free_list = fblk->floats[0].u.chain;
6466 lisp_align_free (fblk);
6467 }
6468 else
6469 {
6470 num_free += this_free;
6471 fprev = &fblk->next;
6472 }
6473 }
6474 total_floats = num_used;
6475 total_free_floats = num_free;
6476 }
6477 6435
6478 /* Put all unmarked intervals on free list. */ 6436 for (fblk = float_block; fblk; fblk = *fprev)
6479 { 6437 {
6480 register struct interval_block *iblk; 6438 register int i;
6481 struct interval_block **iprev = &interval_block; 6439 int this_free = 0;
6482 register int lim = interval_block_index; 6440 for (i = 0; i < lim; i++)
6483 EMACS_INT num_free = 0, num_used = 0; 6441 if (!FLOAT_MARKED_P (&fblk->floats[i]))
6442 {
6443 this_free++;
6444 fblk->floats[i].u.chain = float_free_list;
6445 float_free_list = &fblk->floats[i];
6446 }
6447 else
6448 {
6449 num_used++;
6450 FLOAT_UNMARK (&fblk->floats[i]);
6451 }
6452 lim = FLOAT_BLOCK_SIZE;
6453 /* If this block contains only free floats and we have already
6454 seen more than two blocks worth of free floats then deallocate
6455 this block. */
6456 if (this_free == FLOAT_BLOCK_SIZE && num_free > FLOAT_BLOCK_SIZE)
6457 {
6458 *fprev = fblk->next;
6459 /* Unhook from the free list. */
6460 float_free_list = fblk->floats[0].u.chain;
6461 lisp_align_free (fblk);
6462 }
6463 else
6464 {
6465 num_free += this_free;
6466 fprev = &fblk->next;
6467 }
6468 }
6469 total_floats = num_used;
6470 total_free_floats = num_free;
6471}
6484 6472
6485 interval_free_list = 0; 6473NO_INLINE /* For better stack traces */
6474static void
6475sweep_intervals (void)
6476{
6477 register struct interval_block *iblk;
6478 struct interval_block **iprev = &interval_block;
6479 register int lim = interval_block_index;
6480 EMACS_INT num_free = 0, num_used = 0;
6486 6481
6487 for (iblk = interval_block; iblk; iblk = *iprev) 6482 interval_free_list = 0;
6488 {
6489 register int i;
6490 int this_free = 0;
6491 6483
6492 for (i = 0; i < lim; i++) 6484 for (iblk = interval_block; iblk; iblk = *iprev)
6493 { 6485 {
6494 if (!iblk->intervals[i].gcmarkbit) 6486 register int i;
6495 { 6487 int this_free = 0;
6496 set_interval_parent (&iblk->intervals[i], interval_free_list);
6497 interval_free_list = &iblk->intervals[i];
6498 this_free++;
6499 }
6500 else
6501 {
6502 num_used++;
6503 iblk->intervals[i].gcmarkbit = 0;
6504 }
6505 }
6506 lim = INTERVAL_BLOCK_SIZE;
6507 /* If this block contains only free intervals and we have already
6508 seen more than two blocks worth of free intervals then
6509 deallocate this block. */
6510 if (this_free == INTERVAL_BLOCK_SIZE && num_free > INTERVAL_BLOCK_SIZE)
6511 {
6512 *iprev = iblk->next;
6513 /* Unhook from the free list. */
6514 interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]);
6515 lisp_free (iblk);
6516 }
6517 else
6518 {
6519 num_free += this_free;
6520 iprev = &iblk->next;
6521 }
6522 }
6523 total_intervals = num_used;
6524 total_free_intervals = num_free;
6525 }
6526 6488
6527 /* Put all unmarked symbols on free list. */ 6489 for (i = 0; i < lim; i++)
6528 { 6490 {
6529 register struct symbol_block *sblk; 6491 if (!iblk->intervals[i].gcmarkbit)
6530 struct symbol_block **sprev = &symbol_block; 6492 {
6531 register int lim = symbol_block_index; 6493 set_interval_parent (&iblk->intervals[i], interval_free_list);
6532 EMACS_INT num_free = 0, num_used = 0; 6494 interval_free_list = &iblk->intervals[i];
6495 this_free++;
6496 }
6497 else
6498 {
6499 num_used++;
6500 iblk->intervals[i].gcmarkbit = 0;
6501 }
6502 }
6503 lim = INTERVAL_BLOCK_SIZE;
6504 /* If this block contains only free intervals and we have already
6505 seen more than two blocks worth of free intervals then
6506 deallocate this block. */
6507 if (this_free == INTERVAL_BLOCK_SIZE && num_free > INTERVAL_BLOCK_SIZE)
6508 {
6509 *iprev = iblk->next;
6510 /* Unhook from the free list. */
6511 interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]);
6512 lisp_free (iblk);
6513 }
6514 else
6515 {
6516 num_free += this_free;
6517 iprev = &iblk->next;
6518 }
6519 }
6520 total_intervals = num_used;
6521 total_free_intervals = num_free;
6522}
6533 6523
6534 symbol_free_list = NULL; 6524NO_INLINE /* For better stack traces */
6525static void
6526sweep_symbols (void)
6527{
6528 register struct symbol_block *sblk;
6529 struct symbol_block **sprev = &symbol_block;
6530 register int lim = symbol_block_index;
6531 EMACS_INT num_free = 0, num_used = 0;
6535 6532
6536 for (sblk = symbol_block; sblk; sblk = *sprev) 6533 symbol_free_list = NULL;
6537 {
6538 int this_free = 0;
6539 union aligned_Lisp_Symbol *sym = sblk->symbols;
6540 union aligned_Lisp_Symbol *end = sym + lim;
6541 6534
6542 for (; sym < end; ++sym) 6535 for (sblk = symbol_block; sblk; sblk = *sprev)
6543 { 6536 {
6544 /* Check if the symbol was created during loadup. In such a case 6537 int this_free = 0;
6545 it might be pointed to by pure bytecode which we don't trace, 6538 union aligned_Lisp_Symbol *sym = sblk->symbols;
6546 so we conservatively assume that it is live. */ 6539 union aligned_Lisp_Symbol *end = sym + lim;
6547 bool pure_p = PURE_POINTER_P (XSTRING (sym->s.name));
6548 6540
6549 if (!sym->s.gcmarkbit && !pure_p) 6541 for (; sym < end; ++sym)
6550 { 6542 {
6551 if (sym->s.redirect == SYMBOL_LOCALIZED) 6543 /* Check if the symbol was created during loadup. In such a case
6552 xfree (SYMBOL_BLV (&sym->s)); 6544 it might be pointed to by pure bytecode which we don't trace,
6553 sym->s.next = symbol_free_list; 6545 so we conservatively assume that it is live. */
6554 symbol_free_list = &sym->s; 6546 bool pure_p = PURE_POINTER_P (XSTRING (sym->s.name));
6547
6548 if (!sym->s.gcmarkbit && !pure_p)
6549 {
6550 if (sym->s.redirect == SYMBOL_LOCALIZED)
6551 xfree (SYMBOL_BLV (&sym->s));
6552 sym->s.next = symbol_free_list;
6553 symbol_free_list = &sym->s;
6555#if GC_MARK_STACK 6554#if GC_MARK_STACK
6556 symbol_free_list->function = Vdead; 6555 symbol_free_list->function = Vdead;
6557#endif 6556#endif
6558 ++this_free; 6557 ++this_free;
6559 } 6558 }
6560 else 6559 else
6561 { 6560 {
6562 ++num_used; 6561 ++num_used;
6563 if (!pure_p) 6562 if (!pure_p)
6564 eassert (!STRING_MARKED_P (XSTRING (sym->s.name))); 6563 eassert (!STRING_MARKED_P (XSTRING (sym->s.name)));
6565 sym->s.gcmarkbit = 0; 6564 sym->s.gcmarkbit = 0;
6566 } 6565 }
6567 } 6566 }
6568 6567
6569 lim = SYMBOL_BLOCK_SIZE; 6568 lim = SYMBOL_BLOCK_SIZE;
6570 /* If this block contains only free symbols and we have already 6569 /* If this block contains only free symbols and we have already
6571 seen more than two blocks worth of free symbols then deallocate 6570 seen more than two blocks worth of free symbols then deallocate
6572 this block. */ 6571 this block. */
6573 if (this_free == SYMBOL_BLOCK_SIZE && num_free > SYMBOL_BLOCK_SIZE) 6572 if (this_free == SYMBOL_BLOCK_SIZE && num_free > SYMBOL_BLOCK_SIZE)
6574 { 6573 {
6575 *sprev = sblk->next; 6574 *sprev = sblk->next;
6576 /* Unhook from the free list. */ 6575 /* Unhook from the free list. */
6577 symbol_free_list = sblk->symbols[0].s.next; 6576 symbol_free_list = sblk->symbols[0].s.next;
6578 lisp_free (sblk); 6577 lisp_free (sblk);
6579 } 6578 }
6580 else 6579 else
6581 { 6580 {
6582 num_free += this_free; 6581 num_free += this_free;
6583 sprev = &sblk->next; 6582 sprev = &sblk->next;
6584 } 6583 }
6585 } 6584 }
6586 total_symbols = num_used; 6585 total_symbols = num_used;
6587 total_free_symbols = num_free; 6586 total_free_symbols = num_free;
6588 } 6587}
6589 6588
6590 /* Put all unmarked misc's on free list. 6589NO_INLINE /* For better stack traces */
6591 For a marker, first unchain it from the buffer it points into. */ 6590static void
6592 { 6591sweep_misc (void)
6593 register struct marker_block *mblk; 6592{
6594 struct marker_block **mprev = &marker_block; 6593 register struct marker_block *mblk;
6595 register int lim = marker_block_index; 6594 struct marker_block **mprev = &marker_block;
6596 EMACS_INT num_free = 0, num_used = 0; 6595 register int lim = marker_block_index;
6596 EMACS_INT num_free = 0, num_used = 0;
6597 6597
6598 marker_free_list = 0; 6598 /* Put all unmarked misc's on free list. For a marker, first
6599 unchain it from the buffer it points into. */
6599 6600
6600 for (mblk = marker_block; mblk; mblk = *mprev) 6601 marker_free_list = 0;
6601 {
6602 register int i;
6603 int this_free = 0;
6604 6602
6605 for (i = 0; i < lim; i++) 6603 for (mblk = marker_block; mblk; mblk = *mprev)
6606 { 6604 {
6607 if (!mblk->markers[i].m.u_any.gcmarkbit) 6605 register int i;
6608 { 6606 int this_free = 0;
6609 if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker)
6610 unchain_marker (&mblk->markers[i].m.u_marker);
6611 /* Set the type of the freed object to Lisp_Misc_Free.
6612 We could leave the type alone, since nobody checks it,
6613 but this might catch bugs faster. */
6614 mblk->markers[i].m.u_marker.type = Lisp_Misc_Free;
6615 mblk->markers[i].m.u_free.chain = marker_free_list;
6616 marker_free_list = &mblk->markers[i].m;
6617 this_free++;
6618 }
6619 else
6620 {
6621 num_used++;
6622 mblk->markers[i].m.u_any.gcmarkbit = 0;
6623 }
6624 }
6625 lim = MARKER_BLOCK_SIZE;
6626 /* If this block contains only free markers and we have already
6627 seen more than two blocks worth of free markers then deallocate
6628 this block. */
6629 if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE)
6630 {
6631 *mprev = mblk->next;
6632 /* Unhook from the free list. */
6633 marker_free_list = mblk->markers[0].m.u_free.chain;
6634 lisp_free (mblk);
6635 }
6636 else
6637 {
6638 num_free += this_free;
6639 mprev = &mblk->next;
6640 }
6641 }
6642 6607
6643 total_markers = num_used; 6608 for (i = 0; i < lim; i++)
6644 total_free_markers = num_free; 6609 {
6645 } 6610 if (!mblk->markers[i].m.u_any.gcmarkbit)
6611 {
6612 if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker)
6613 unchain_marker (&mblk->markers[i].m.u_marker);
6614 /* Set the type of the freed object to Lisp_Misc_Free.
6615 We could leave the type alone, since nobody checks it,
6616 but this might catch bugs faster. */
6617 mblk->markers[i].m.u_marker.type = Lisp_Misc_Free;
6618 mblk->markers[i].m.u_free.chain = marker_free_list;
6619 marker_free_list = &mblk->markers[i].m;
6620 this_free++;
6621 }
6622 else
6623 {
6624 num_used++;
6625 mblk->markers[i].m.u_any.gcmarkbit = 0;
6626 }
6627 }
6628 lim = MARKER_BLOCK_SIZE;
6629 /* If this block contains only free markers and we have already
6630 seen more than two blocks worth of free markers then deallocate
6631 this block. */
6632 if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE)
6633 {
6634 *mprev = mblk->next;
6635 /* Unhook from the free list. */
6636 marker_free_list = mblk->markers[0].m.u_free.chain;
6637 lisp_free (mblk);
6638 }
6639 else
6640 {
6641 num_free += this_free;
6642 mprev = &mblk->next;
6643 }
6644 }
6646 6645
6647 /* Free all unmarked buffers */ 6646 total_markers = num_used;
6648 { 6647 total_free_markers = num_free;
6649 register struct buffer *buffer, **bprev = &all_buffers; 6648}
6650 6649
6651 total_buffers = 0; 6650NO_INLINE /* For better stack traces */
6652 for (buffer = all_buffers; buffer; buffer = *bprev) 6651static void
6653 if (!VECTOR_MARKED_P (buffer)) 6652sweep_buffers (void)
6654 { 6653{
6655 *bprev = buffer->next; 6654 register struct buffer *buffer, **bprev = &all_buffers;
6656 lisp_free (buffer);
6657 }
6658 else
6659 {
6660 VECTOR_UNMARK (buffer);
6661 /* Do not use buffer_(set|get)_intervals here. */
6662 buffer->text->intervals = balance_intervals (buffer->text->intervals);
6663 total_buffers++;
6664 bprev = &buffer->next;
6665 }
6666 }
6667 6655
6668 sweep_vectors (); 6656 total_buffers = 0;
6669 check_string_bytes (!noninteractive); 6657 for (buffer = all_buffers; buffer; buffer = *bprev)
6658 if (!VECTOR_MARKED_P (buffer))
6659 {
6660 *bprev = buffer->next;
6661 lisp_free (buffer);
6662 }
6663 else
6664 {
6665 VECTOR_UNMARK (buffer);
6666 /* Do not use buffer_(set|get)_intervals here. */
6667 buffer->text->intervals = balance_intervals (buffer->text->intervals);
6668 total_buffers++;
6669 bprev = &buffer->next;
6670 }
6670} 6671}
6671 6672
6673/* Sweep: find all structures not marked, and free them. */
6674static void
6675gc_sweep (void)
6676{
6677 /* Remove or mark entries in weak hash tables.
6678 This must be done before any object is unmarked. */
6679 sweep_weak_hash_tables ();
6672 6680
6681 sweep_strings ();
6682 check_string_bytes (!noninteractive);
6683 sweep_conses ();
6684 sweep_floats ();
6685 sweep_intervals ();
6686 sweep_symbols ();
6687 sweep_misc ();
6688 sweep_buffers ();
6689 sweep_vectors ();
6690 check_string_bytes (!noninteractive);
6691}
6673 6692
6674 6693
6675/* Debugging aids. */ 6694/* Debugging aids. */
diff --git a/src/fns.c b/src/fns.c
index 499e4b490a6..cf799344c32 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -4032,6 +4032,7 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p)
4032 current garbage collection. Remove weak tables that don't survive 4032 current garbage collection. Remove weak tables that don't survive
4033 from Vweak_hash_tables. Called from gc_sweep. */ 4033 from Vweak_hash_tables. Called from gc_sweep. */
4034 4034
4035NO_INLINE /* For better stack traces */
4035void 4036void
4036sweep_weak_hash_tables (void) 4037sweep_weak_hash_tables (void)
4037{ 4038{