diff options
| author | Daniel Colascione | 2014-03-23 14:58:41 -0700 |
|---|---|---|
| committer | Daniel Colascione | 2014-03-23 14:58:41 -0700 |
| commit | b029599f767406002ea892d0bd40420de0a954f6 (patch) | |
| tree | 2737840e08cbc05981c4598b9525b8c30ce7977a /src/alloc.c | |
| parent | 835af7195792e9e736a6acc3ef51b21e23020c2c (diff) | |
| parent | 577b2ffd2d787506261ed758b086fb4257116dba (diff) | |
| download | emacs-b029599f767406002ea892d0bd40420de0a954f6.tar.gz emacs-b029599f767406002ea892d0bd40420de0a954f6.zip | |
Clean up gc_sweep
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 613 |
1 files changed, 316 insertions, 297 deletions
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 | ||
| 1820 | NO_INLINE /* For better stack traces */ | ||
| 1820 | static void | 1821 | static void |
| 1821 | sweep_strings (void) | 1822 | sweep_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 | ||
| 2937 | NO_INLINE /* For better stack traces */ | ||
| 2936 | static void | 2938 | static void |
| 2937 | sweep_vectors (void) | 2939 | sweep_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 | ||
| 6346 | NO_INLINE /* For better stack traces */ | ||
| 6345 | static void | 6347 | static void |
| 6346 | gc_sweep (void) | 6348 | sweep_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; | 6425 | NO_INLINE /* For better stack traces */ |
| 6426 | static void | ||
| 6427 | sweep_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; | 6473 | NO_INLINE /* For better stack traces */ |
| 6474 | static void | ||
| 6475 | sweep_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; | 6524 | NO_INLINE /* For better stack traces */ |
| 6525 | static void | ||
| 6526 | sweep_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. | 6589 | NO_INLINE /* For better stack traces */ |
| 6591 | For a marker, first unchain it from the buffer it points into. */ | 6590 | static void |
| 6592 | { | 6591 | sweep_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; | 6650 | NO_INLINE /* For better stack traces */ |
| 6652 | for (buffer = all_buffers; buffer; buffer = *bprev) | 6651 | static void |
| 6653 | if (!VECTOR_MARKED_P (buffer)) | 6652 | sweep_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. */ | ||
| 6674 | static void | ||
| 6675 | gc_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. */ |