diff options
| author | Dmitry Antipov | 2012-07-18 09:44:36 +0400 |
|---|---|---|
| committer | Dmitry Antipov | 2012-07-18 09:44:36 +0400 |
| commit | 3ab6e069695d0dd5bb77133a89f858190ab8550a (patch) | |
| tree | bd50490ec50ec8d5f72625fd38840d1283983561 /src/alloc.c | |
| parent | 0a60bc107123321438fc1320ab34fcf588ec7128 (diff) | |
| download | emacs-3ab6e069695d0dd5bb77133a89f858190ab8550a.tar.gz emacs-3ab6e069695d0dd5bb77133a89f858190ab8550a.zip | |
Return more descriptive data from Fgarbage_collect.
Suggested by Stefan Monnier in
http://lists.gnu.org/archive/html/emacs-devel/2012-07/msg00369.html.
* src/alloc.c (bounded_number): New function.
(total_buffers, total_vectors): New variable.
(total_string_size): Rename to total_string_bytes, adjust users.
(total_vector_size): Rename to total_vector_bytes, adjust users.
(sweep_vectors): Account total_vectors and total_vector_bytes.
(Fgarbage_collect): New return value. Adjust documentation.
(gc_sweep): Account total_buffers.
(Fmemory_free, Fmemory_use_counts): Use bounded_number.
(VECTOR_SIZE): Remove.
* src/data.c (Qfloat, Qvector, Qsymbol, Qstring, Qcons): Make global.
(Qinterval, Qmisc): New symbols.
(syms_of_data): Initialize them.
* src/lisp.h (Qinterval, Qsymbol, Qstring, Qmisc, Qvector, Qfloat)
(Qcons, Qbuffer): New declarations.
* lisp/emacs-lisp/chart.el (chart-emacs-storage): Change to
reflect new format of data returned by Fgarbage_collect.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 149 |
1 files changed, 92 insertions, 57 deletions
diff --git a/src/alloc.c b/src/alloc.c index 7ab3f7b5e9c..b891d32d164 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -189,9 +189,9 @@ int abort_on_gc; | |||
| 189 | 189 | ||
| 190 | /* Number of live and free conses etc. */ | 190 | /* Number of live and free conses etc. */ |
| 191 | 191 | ||
| 192 | static EMACS_INT total_conses, total_markers, total_symbols, total_vector_size; | 192 | static EMACS_INT total_conses, total_markers, total_symbols, total_buffers; |
| 193 | static EMACS_INT total_free_conses, total_free_markers, total_free_symbols; | 193 | static EMACS_INT total_free_conses, total_free_markers, total_free_symbols; |
| 194 | static EMACS_INT total_free_floats, total_floats, total_free_vector_bytes; | 194 | static EMACS_INT total_free_floats, total_floats; |
| 195 | 195 | ||
| 196 | /* Points to memory space allocated as "spare", to be freed if we run | 196 | /* Points to memory space allocated as "spare", to be freed if we run |
| 197 | out of memory. We keep one large block, four cons-blocks, and | 197 | out of memory. We keep one large block, four cons-blocks, and |
| @@ -1708,7 +1708,7 @@ static EMACS_INT total_strings, total_free_strings; | |||
| 1708 | 1708 | ||
| 1709 | /* Number of bytes used by live strings. */ | 1709 | /* Number of bytes used by live strings. */ |
| 1710 | 1710 | ||
| 1711 | static EMACS_INT total_string_size; | 1711 | static EMACS_INT total_string_bytes; |
| 1712 | 1712 | ||
| 1713 | /* Given a pointer to a Lisp_String S which is on the free-list | 1713 | /* Given a pointer to a Lisp_String S which is on the free-list |
| 1714 | string_free_list, return a pointer to its successor in the | 1714 | string_free_list, return a pointer to its successor in the |
| @@ -2081,7 +2081,7 @@ sweep_strings (void) | |||
| 2081 | 2081 | ||
| 2082 | string_free_list = NULL; | 2082 | string_free_list = NULL; |
| 2083 | total_strings = total_free_strings = 0; | 2083 | total_strings = total_free_strings = 0; |
| 2084 | total_string_size = 0; | 2084 | total_string_bytes = 0; |
| 2085 | 2085 | ||
| 2086 | /* Scan strings_blocks, free Lisp_Strings that aren't marked. */ | 2086 | /* Scan strings_blocks, free Lisp_Strings that aren't marked. */ |
| 2087 | for (b = string_blocks; b; b = next) | 2087 | for (b = string_blocks; b; b = next) |
| @@ -2107,7 +2107,7 @@ sweep_strings (void) | |||
| 2107 | UNMARK_BALANCE_INTERVALS (s->intervals); | 2107 | UNMARK_BALANCE_INTERVALS (s->intervals); |
| 2108 | 2108 | ||
| 2109 | ++total_strings; | 2109 | ++total_strings; |
| 2110 | total_string_size += STRING_BYTES (s); | 2110 | total_string_bytes += STRING_BYTES (s); |
| 2111 | } | 2111 | } |
| 2112 | else | 2112 | else |
| 2113 | { | 2113 | { |
| @@ -2957,6 +2957,14 @@ static struct Lisp_Vector *large_vectors; | |||
| 2957 | 2957 | ||
| 2958 | Lisp_Object zero_vector; | 2958 | Lisp_Object zero_vector; |
| 2959 | 2959 | ||
| 2960 | /* Number of live vectors. */ | ||
| 2961 | |||
| 2962 | static EMACS_INT total_vectors; | ||
| 2963 | |||
| 2964 | /* Number of bytes used by live and free vectors. */ | ||
| 2965 | |||
| 2966 | static EMACS_INT total_vector_bytes, total_free_vector_bytes; | ||
| 2967 | |||
| 2960 | /* Get a new vector block. */ | 2968 | /* Get a new vector block. */ |
| 2961 | 2969 | ||
| 2962 | static struct vector_block * | 2970 | static struct vector_block * |
| @@ -3047,12 +3055,6 @@ allocate_vector_from_block (size_t nbytes) | |||
| 3047 | return vector; | 3055 | return vector; |
| 3048 | } | 3056 | } |
| 3049 | 3057 | ||
| 3050 | /* Return how many Lisp_Objects can be stored in V. */ | ||
| 3051 | |||
| 3052 | #define VECTOR_SIZE(v) ((v)->header.size & PSEUDOVECTOR_FLAG ? \ | ||
| 3053 | (PSEUDOVECTOR_SIZE_MASK & (v)->header.size) : \ | ||
| 3054 | (v)->header.size) | ||
| 3055 | |||
| 3056 | /* Nonzero if VECTOR pointer is valid pointer inside BLOCK. */ | 3058 | /* Nonzero if VECTOR pointer is valid pointer inside BLOCK. */ |
| 3057 | 3059 | ||
| 3058 | #define VECTOR_IN_BLOCK(vector, block) \ | 3060 | #define VECTOR_IN_BLOCK(vector, block) \ |
| @@ -3077,7 +3079,7 @@ sweep_vectors (void) | |||
| 3077 | struct vector_block *block = vector_blocks, **bprev = &vector_blocks; | 3079 | struct vector_block *block = vector_blocks, **bprev = &vector_blocks; |
| 3078 | struct Lisp_Vector *vector, *next, **vprev = &large_vectors; | 3080 | struct Lisp_Vector *vector, *next, **vprev = &large_vectors; |
| 3079 | 3081 | ||
| 3080 | total_free_vector_bytes = total_vector_size = 0; | 3082 | total_vectors = total_vector_bytes = total_free_vector_bytes = 0; |
| 3081 | memset (vector_free_lists, 0, sizeof (vector_free_lists)); | 3083 | memset (vector_free_lists, 0, sizeof (vector_free_lists)); |
| 3082 | 3084 | ||
| 3083 | /* Looking through vector blocks. */ | 3085 | /* Looking through vector blocks. */ |
| @@ -3092,7 +3094,8 @@ sweep_vectors (void) | |||
| 3092 | if (VECTOR_MARKED_P (vector)) | 3094 | if (VECTOR_MARKED_P (vector)) |
| 3093 | { | 3095 | { |
| 3094 | VECTOR_UNMARK (vector); | 3096 | VECTOR_UNMARK (vector); |
| 3095 | total_vector_size += VECTOR_SIZE (vector); | 3097 | total_vectors++; |
| 3098 | total_vector_bytes += vector->header.next.nbytes; | ||
| 3096 | next = ADVANCE (vector, vector->header.next.nbytes); | 3099 | next = ADVANCE (vector, vector->header.next.nbytes); |
| 3097 | } | 3100 | } |
| 3098 | else | 3101 | else |
| @@ -3148,7 +3151,12 @@ sweep_vectors (void) | |||
| 3148 | if (VECTOR_MARKED_P (vector)) | 3151 | if (VECTOR_MARKED_P (vector)) |
| 3149 | { | 3152 | { |
| 3150 | VECTOR_UNMARK (vector); | 3153 | VECTOR_UNMARK (vector); |
| 3151 | total_vector_size += VECTOR_SIZE (vector); | 3154 | total_vectors++; |
| 3155 | /* All pseudovectors are small enough to be allocated from | ||
| 3156 | vector blocks. This code should be redesigned if some | ||
| 3157 | pseudovector type grows beyond VBLOCK_BYTES_MAX. */ | ||
| 3158 | eassert (!(vector->header.size & PSEUDOVECTOR_FLAG)); | ||
| 3159 | total_vector_bytes += header_size + vector->header.size * word_size; | ||
| 3152 | vprev = &vector->header.next.vector; | 3160 | vprev = &vector->header.next.vector; |
| 3153 | } | 3161 | } |
| 3154 | else | 3162 | else |
| @@ -5339,16 +5347,28 @@ inhibit_garbage_collection (void) | |||
| 5339 | return count; | 5347 | return count; |
| 5340 | } | 5348 | } |
| 5341 | 5349 | ||
| 5350 | /* Used to avoid possible overflows when | ||
| 5351 | converting from C to Lisp integers. */ | ||
| 5352 | |||
| 5353 | static inline Lisp_Object | ||
| 5354 | bounded_number (EMACS_INT number) | ||
| 5355 | { | ||
| 5356 | return make_number (min (MOST_POSITIVE_FIXNUM, number)); | ||
| 5357 | } | ||
| 5342 | 5358 | ||
| 5343 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", | 5359 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", |
| 5344 | doc: /* Reclaim storage for Lisp objects no longer needed. | 5360 | doc: /* Reclaim storage for Lisp objects no longer needed. |
| 5345 | Garbage collection happens automatically if you cons more than | 5361 | Garbage collection happens automatically if you cons more than |
| 5346 | `gc-cons-threshold' bytes of Lisp data since previous garbage collection. | 5362 | `gc-cons-threshold' bytes of Lisp data since previous garbage collection. |
| 5347 | `garbage-collect' normally returns a list with info on amount of space in use: | 5363 | `garbage-collect' normally returns a list with info on amount of space in use: |
| 5348 | ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS) | 5364 | ((CONS INTERNAL-SIZE USED-CONSES FREE-CONSES) |
| 5349 | (USED-MISCS . FREE-MISCS) USED-STRING-CHARS USED-VECTOR-SLOTS | 5365 | (SYMBOL INTERNAL-SIZE USED-SYMBOLS FREE-SYMBOLS) |
| 5350 | (USED-FLOATS . FREE-FLOATS) (USED-INTERVALS . FREE-INTERVALS) | 5366 | (MISC INTERNAL-SIZE USED-MISCS FREE-MISCS) |
| 5351 | (USED-STRINGS . FREE-STRINGS)) | 5367 | (STRING INTERNAL-SIZE USED-STRINGS USED-STRING-BYTES FREE-STRING) |
| 5368 | (VECTOR INTERNAL-SIZE USED-VECTORS USED-VECTOR-BYTES FREE-VECTOR-BYTES) | ||
| 5369 | (FLOAT INTERNAL-SIZE USED-FLOATS FREE-FLOATS) | ||
| 5370 | (INTERVAL INTERNAL-SIZE USED-INTERVALS FREE-INTERVALS) | ||
| 5371 | (BUFFER INTERNAL-SIZE USED-BUFFERS)) | ||
| 5352 | However, if there was overflow in pure space, `garbage-collect' | 5372 | However, if there was overflow in pure space, `garbage-collect' |
| 5353 | returns nil, because real GC can't be done. | 5373 | returns nil, because real GC can't be done. |
| 5354 | See Info node `(elisp)Garbage Collection'. */) | 5374 | See Info node `(elisp)Garbage Collection'. */) |
| @@ -5595,8 +5615,8 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5595 | tot += total_conses * sizeof (struct Lisp_Cons); | 5615 | tot += total_conses * sizeof (struct Lisp_Cons); |
| 5596 | tot += total_symbols * sizeof (struct Lisp_Symbol); | 5616 | tot += total_symbols * sizeof (struct Lisp_Symbol); |
| 5597 | tot += total_markers * sizeof (union Lisp_Misc); | 5617 | tot += total_markers * sizeof (union Lisp_Misc); |
| 5598 | tot += total_string_size; | 5618 | tot += total_string_bytes; |
| 5599 | tot += total_vector_size * sizeof (Lisp_Object); | 5619 | tot += total_vector_bytes; |
| 5600 | tot += total_floats * sizeof (struct Lisp_Float); | 5620 | tot += total_floats * sizeof (struct Lisp_Float); |
| 5601 | tot += total_intervals * sizeof (struct interval); | 5621 | tot += total_intervals * sizeof (struct interval); |
| 5602 | tot += total_strings * sizeof (struct Lisp_String); | 5622 | tot += total_strings * sizeof (struct Lisp_String); |
| @@ -5621,20 +5641,38 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5621 | 5641 | ||
| 5622 | unbind_to (count, Qnil); | 5642 | unbind_to (count, Qnil); |
| 5623 | 5643 | ||
| 5624 | total[0] = Fcons (make_number (total_conses), | 5644 | total[0] = list4 (Qcons, make_number (sizeof (struct Lisp_Cons)), |
| 5625 | make_number (total_free_conses)); | 5645 | bounded_number (total_conses), |
| 5626 | total[1] = Fcons (make_number (total_symbols), | 5646 | bounded_number (total_free_conses)); |
| 5627 | make_number (total_free_symbols)); | 5647 | |
| 5628 | total[2] = Fcons (make_number (total_markers), | 5648 | total[1] = list4 (Qsymbol, make_number (sizeof (struct Lisp_Symbol)), |
| 5629 | make_number (total_free_markers)); | 5649 | bounded_number (total_symbols), |
| 5630 | total[3] = make_number (total_string_size); | 5650 | bounded_number (total_free_symbols)); |
| 5631 | total[4] = make_number (total_vector_size); | 5651 | |
| 5632 | total[5] = Fcons (make_number (total_floats), | 5652 | total[2] = list4 (Qmisc, make_number (sizeof (union Lisp_Misc)), |
| 5633 | make_number (total_free_floats)); | 5653 | bounded_number (total_markers), |
| 5634 | total[6] = Fcons (make_number (total_intervals), | 5654 | bounded_number (total_free_markers)); |
| 5635 | make_number (total_free_intervals)); | 5655 | |
| 5636 | total[7] = Fcons (make_number (total_strings), | 5656 | total[3] = list5 (Qstring, make_number (sizeof (struct Lisp_String)), |
| 5637 | make_number (total_free_strings)); | 5657 | bounded_number (total_strings), |
| 5658 | bounded_number (total_string_bytes), | ||
| 5659 | bounded_number (total_free_strings)); | ||
| 5660 | |||
| 5661 | total[4] = list5 (Qvector, make_number (sizeof (struct Lisp_Vector)), | ||
| 5662 | bounded_number (total_vectors), | ||
| 5663 | bounded_number (total_vector_bytes), | ||
| 5664 | bounded_number (total_free_vector_bytes)); | ||
| 5665 | |||
| 5666 | total[5] = list4 (Qfloat, make_number (sizeof (struct Lisp_Float)), | ||
| 5667 | bounded_number (total_floats), | ||
| 5668 | bounded_number (total_free_floats)); | ||
| 5669 | |||
| 5670 | total[6] = list4 (Qinterval, make_number (sizeof (struct interval)), | ||
| 5671 | bounded_number (total_intervals), | ||
| 5672 | bounded_number (total_free_intervals)); | ||
| 5673 | |||
| 5674 | total[7] = list3 (Qbuffer, make_number (sizeof (struct buffer)), | ||
| 5675 | bounded_number (total_buffers)); | ||
| 5638 | 5676 | ||
| 5639 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | 5677 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
| 5640 | { | 5678 | { |
| @@ -6535,6 +6573,7 @@ gc_sweep (void) | |||
| 6535 | { | 6573 | { |
| 6536 | register struct buffer *buffer = all_buffers, *prev = 0, *next; | 6574 | register struct buffer *buffer = all_buffers, *prev = 0, *next; |
| 6537 | 6575 | ||
| 6576 | total_buffers = 0; | ||
| 6538 | while (buffer) | 6577 | while (buffer) |
| 6539 | if (!VECTOR_MARKED_P (buffer)) | 6578 | if (!VECTOR_MARKED_P (buffer)) |
| 6540 | { | 6579 | { |
| @@ -6550,6 +6589,7 @@ gc_sweep (void) | |||
| 6550 | { | 6589 | { |
| 6551 | VECTOR_UNMARK (buffer); | 6590 | VECTOR_UNMARK (buffer); |
| 6552 | UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer)); | 6591 | UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer)); |
| 6592 | total_buffers++; | ||
| 6553 | prev = buffer, buffer = buffer->header.next.buffer; | 6593 | prev = buffer, buffer = buffer->header.next.buffer; |
| 6554 | } | 6594 | } |
| 6555 | } | 6595 | } |
| @@ -6592,22 +6632,17 @@ if heap statistics are not available. Both counters are in units of | |||
| 6592 | Lisp_Object val = Fmake_list (make_number (2), make_number (0)); | 6632 | Lisp_Object val = Fmake_list (make_number (2), make_number (0)); |
| 6593 | 6633 | ||
| 6594 | XSETCAR (val, | 6634 | XSETCAR (val, |
| 6595 | (make_number | 6635 | bounded_number |
| 6596 | (min (MOST_POSITIVE_FIXNUM, | 6636 | ((total_free_conses * sizeof (struct Lisp_Cons) |
| 6597 | ((total_free_conses * sizeof (struct Lisp_Cons) | 6637 | + total_free_markers * sizeof (union Lisp_Misc) |
| 6598 | + total_free_markers * sizeof (union Lisp_Misc) | 6638 | + total_free_symbols * sizeof (struct Lisp_Symbol) |
| 6599 | + total_free_symbols * sizeof (struct Lisp_Symbol) | 6639 | + total_free_floats * sizeof (struct Lisp_Float) |
| 6600 | + total_free_floats * sizeof (struct Lisp_Float) | 6640 | + total_free_intervals * sizeof (struct interval) |
| 6601 | + total_free_intervals * sizeof (struct interval) | 6641 | + total_free_strings * sizeof (struct Lisp_String) |
| 6602 | + total_free_strings * sizeof (struct Lisp_String) | 6642 | + total_free_vector_bytes |
| 6603 | + total_free_vector_bytes | 6643 | + 1023) >> 10)); |
| 6604 | + 1023) | ||
| 6605 | >> 10))))); | ||
| 6606 | |||
| 6607 | #ifdef DOUG_LEA_MALLOC | 6644 | #ifdef DOUG_LEA_MALLOC |
| 6608 | XSETCAR (XCDR (val), | 6645 | XSETCAR (XCDR (val), bounded_number ((mallinfo ().fordblks + 1023) >> 10)); |
| 6609 | make_number (min (MOST_POSITIVE_FIXNUM, | ||
| 6610 | (mallinfo ().fordblks + 1023) >> 10))); | ||
| 6611 | #endif | 6646 | #endif |
| 6612 | return val; | 6647 | return val; |
| 6613 | } | 6648 | } |
| @@ -6629,14 +6664,14 @@ Frames, windows, buffers, and subprocesses count as vectors | |||
| 6629 | { | 6664 | { |
| 6630 | Lisp_Object consed[8]; | 6665 | Lisp_Object consed[8]; |
| 6631 | 6666 | ||
| 6632 | consed[0] = make_number (min (MOST_POSITIVE_FIXNUM, cons_cells_consed)); | 6667 | consed[0] = bounded_number (cons_cells_consed); |
| 6633 | consed[1] = make_number (min (MOST_POSITIVE_FIXNUM, floats_consed)); | 6668 | consed[1] = bounded_number (floats_consed); |
| 6634 | consed[2] = make_number (min (MOST_POSITIVE_FIXNUM, vector_cells_consed)); | 6669 | consed[2] = bounded_number (vector_cells_consed); |
| 6635 | consed[3] = make_number (min (MOST_POSITIVE_FIXNUM, symbols_consed)); | 6670 | consed[3] = bounded_number (symbols_consed); |
| 6636 | consed[4] = make_number (min (MOST_POSITIVE_FIXNUM, string_chars_consed)); | 6671 | consed[4] = bounded_number (string_chars_consed); |
| 6637 | consed[5] = make_number (min (MOST_POSITIVE_FIXNUM, misc_objects_consed)); | 6672 | consed[5] = bounded_number (misc_objects_consed); |
| 6638 | consed[6] = make_number (min (MOST_POSITIVE_FIXNUM, intervals_consed)); | 6673 | consed[6] = bounded_number (intervals_consed); |
| 6639 | consed[7] = make_number (min (MOST_POSITIVE_FIXNUM, strings_consed)); | 6674 | consed[7] = bounded_number (strings_consed); |
| 6640 | 6675 | ||
| 6641 | return Flist (8, consed); | 6676 | return Flist (8, consed); |
| 6642 | } | 6677 | } |