diff options
| author | Paul Eggert | 2019-03-01 09:01:59 -0800 |
|---|---|---|
| committer | Paul Eggert | 2019-03-01 09:09:47 -0800 |
| commit | 7e29eae023c8158d41eba02c2367e70cbee53642 (patch) | |
| tree | 6679f45eba3b0b06dfb8ba4353b259445b6c1340 /src | |
| parent | fb52d961a40d889d87628058be6ea8116ced2e13 (diff) | |
| download | emacs-7e29eae023c8158d41eba02c2367e70cbee53642.tar.gz emacs-7e29eae023c8158d41eba02c2367e70cbee53642.zip | |
Suppress GC stats when obviously not needed
This should help future improvements where these stats can be
bignums that do not fit into intmax_t.
* src/alloc.c (struct gcstat, gcstat): New type and static var,
to package up GC statistics into one C object. It replaces ...
(total_free_intervals, total_intervals, total_strings)
(total_free_strings, total_string_bytes, total_vectors)
(total_vector_slots, total_free_vector_slots): ... these
removed static vars. All uses changed.
(garbage_collect_1): Accept a struct gcstat *, not a void *
which was not used anymore anyway. Return a bool indicating
success, instead of a Lisp object. All callers changed.
(garbage_collect): New function. All C callers of
Fgarbage_collect changed to use it, since none of them use the
return value. Now, only Lisp code uses Fgarbage_collect.
(Fgarbage_collect): No longer noinline. Cons up the return
value here, not in garbage_collect_1.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 237 | ||||
| -rw-r--r-- | src/lisp.h | 3 | ||||
| -rw-r--r-- | src/pdumper.c | 2 |
3 files changed, 116 insertions, 126 deletions
diff --git a/src/alloc.c b/src/alloc.c index a0d0a611346..7d63e3c79b6 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -253,9 +253,17 @@ typedef intptr_t object_ct; | |||
| 253 | 253 | ||
| 254 | /* Number of live and free conses etc. */ | 254 | /* Number of live and free conses etc. */ |
| 255 | 255 | ||
| 256 | static object_ct total_conses, total_symbols, total_buffers; | 256 | struct gcstat |
| 257 | static object_ct total_free_conses, total_free_symbols; | 257 | { |
| 258 | static object_ct total_free_floats, total_floats; | 258 | object_ct total_conses, total_free_conses; |
| 259 | object_ct total_symbols, total_free_symbols; | ||
| 260 | object_ct total_strings, total_free_strings; | ||
| 261 | byte_ct total_string_bytes; | ||
| 262 | object_ct total_vectors, total_vector_slots, total_free_vector_slots; | ||
| 263 | object_ct total_floats, total_free_floats; | ||
| 264 | object_ct total_intervals, total_free_intervals; | ||
| 265 | object_ct total_buffers; | ||
| 266 | } gcstat; | ||
| 259 | 267 | ||
| 260 | /* Points to memory space allocated as "spare", to be freed if we run | 268 | /* Points to memory space allocated as "spare", to be freed if we run |
| 261 | out of memory. We keep one large block, four cons-blocks, and | 269 | out of memory. We keep one large block, four cons-blocks, and |
| @@ -1538,10 +1546,6 @@ static struct interval_block *interval_block; | |||
| 1538 | 1546 | ||
| 1539 | static int interval_block_index = INTERVAL_BLOCK_SIZE; | 1547 | static int interval_block_index = INTERVAL_BLOCK_SIZE; |
| 1540 | 1548 | ||
| 1541 | /* Number of free and live intervals. */ | ||
| 1542 | |||
| 1543 | static object_ct total_free_intervals, total_intervals; | ||
| 1544 | |||
| 1545 | /* List of free intervals. */ | 1549 | /* List of free intervals. */ |
| 1546 | 1550 | ||
| 1547 | static INTERVAL interval_free_list; | 1551 | static INTERVAL interval_free_list; |
| @@ -1570,7 +1574,7 @@ make_interval (void) | |||
| 1570 | newi->next = interval_block; | 1574 | newi->next = interval_block; |
| 1571 | interval_block = newi; | 1575 | interval_block = newi; |
| 1572 | interval_block_index = 0; | 1576 | interval_block_index = 0; |
| 1573 | total_free_intervals += INTERVAL_BLOCK_SIZE; | 1577 | gcstat.total_free_intervals += INTERVAL_BLOCK_SIZE; |
| 1574 | } | 1578 | } |
| 1575 | val = &interval_block->intervals[interval_block_index++]; | 1579 | val = &interval_block->intervals[interval_block_index++]; |
| 1576 | } | 1580 | } |
| @@ -1579,7 +1583,7 @@ make_interval (void) | |||
| 1579 | 1583 | ||
| 1580 | consing_since_gc += sizeof (struct interval); | 1584 | consing_since_gc += sizeof (struct interval); |
| 1581 | intervals_consed++; | 1585 | intervals_consed++; |
| 1582 | total_free_intervals--; | 1586 | gcstat.total_free_intervals--; |
| 1583 | RESET_INTERVAL (val); | 1587 | RESET_INTERVAL (val); |
| 1584 | val->gcmarkbit = 0; | 1588 | val->gcmarkbit = 0; |
| 1585 | return val; | 1589 | return val; |
| @@ -1755,14 +1759,6 @@ static struct string_block *string_blocks; | |||
| 1755 | 1759 | ||
| 1756 | static struct Lisp_String *string_free_list; | 1760 | static struct Lisp_String *string_free_list; |
| 1757 | 1761 | ||
| 1758 | /* Number of live and free Lisp_Strings. */ | ||
| 1759 | |||
| 1760 | static object_ct total_strings, total_free_strings; | ||
| 1761 | |||
| 1762 | /* Number of bytes used by live strings. */ | ||
| 1763 | |||
| 1764 | static byte_ct total_string_bytes; | ||
| 1765 | |||
| 1766 | /* Given a pointer to a Lisp_String S which is on the free-list | 1762 | /* Given a pointer to a Lisp_String S which is on the free-list |
| 1767 | string_free_list, return a pointer to its successor in the | 1763 | string_free_list, return a pointer to its successor in the |
| 1768 | free-list. */ | 1764 | free-list. */ |
| @@ -1972,7 +1968,7 @@ allocate_string (void) | |||
| 1972 | string_free_list = ptr_bounds_clip (s, sizeof *s); | 1968 | string_free_list = ptr_bounds_clip (s, sizeof *s); |
| 1973 | } | 1969 | } |
| 1974 | 1970 | ||
| 1975 | total_free_strings += STRING_BLOCK_SIZE; | 1971 | gcstat.total_free_strings += STRING_BLOCK_SIZE; |
| 1976 | } | 1972 | } |
| 1977 | 1973 | ||
| 1978 | check_string_free_list (); | 1974 | check_string_free_list (); |
| @@ -1983,8 +1979,8 @@ allocate_string (void) | |||
| 1983 | 1979 | ||
| 1984 | MALLOC_UNBLOCK_INPUT; | 1980 | MALLOC_UNBLOCK_INPUT; |
| 1985 | 1981 | ||
| 1986 | --total_free_strings; | 1982 | gcstat.total_free_strings--; |
| 1987 | ++total_strings; | 1983 | gcstat.total_strings++; |
| 1988 | ++strings_consed; | 1984 | ++strings_consed; |
| 1989 | consing_since_gc += sizeof *s; | 1985 | consing_since_gc += sizeof *s; |
| 1990 | 1986 | ||
| @@ -2119,8 +2115,8 @@ sweep_strings (void) | |||
| 2119 | struct string_block *live_blocks = NULL; | 2115 | struct string_block *live_blocks = NULL; |
| 2120 | 2116 | ||
| 2121 | string_free_list = NULL; | 2117 | string_free_list = NULL; |
| 2122 | total_strings = total_free_strings = 0; | 2118 | gcstat.total_strings = gcstat.total_free_strings = 0; |
| 2123 | total_string_bytes = 0; | 2119 | gcstat.total_string_bytes = 0; |
| 2124 | 2120 | ||
| 2125 | /* Scan strings_blocks, free Lisp_Strings that aren't marked. */ | 2121 | /* Scan strings_blocks, free Lisp_Strings that aren't marked. */ |
| 2126 | for (b = string_blocks; b; b = next) | 2122 | for (b = string_blocks; b; b = next) |
| @@ -2145,8 +2141,8 @@ sweep_strings (void) | |||
| 2145 | /* Do not use string_(set|get)_intervals here. */ | 2141 | /* Do not use string_(set|get)_intervals here. */ |
| 2146 | s->u.s.intervals = balance_intervals (s->u.s.intervals); | 2142 | s->u.s.intervals = balance_intervals (s->u.s.intervals); |
| 2147 | 2143 | ||
| 2148 | ++total_strings; | 2144 | gcstat.total_strings++; |
| 2149 | total_string_bytes += STRING_BYTES (s); | 2145 | gcstat.total_string_bytes += STRING_BYTES (s); |
| 2150 | } | 2146 | } |
| 2151 | else | 2147 | else |
| 2152 | { | 2148 | { |
| @@ -2186,14 +2182,14 @@ sweep_strings (void) | |||
| 2186 | /* Free blocks that contain free Lisp_Strings only, except | 2182 | /* Free blocks that contain free Lisp_Strings only, except |
| 2187 | the first two of them. */ | 2183 | the first two of them. */ |
| 2188 | if (nfree == STRING_BLOCK_SIZE | 2184 | if (nfree == STRING_BLOCK_SIZE |
| 2189 | && total_free_strings > STRING_BLOCK_SIZE) | 2185 | && gcstat.total_free_strings > STRING_BLOCK_SIZE) |
| 2190 | { | 2186 | { |
| 2191 | lisp_free (b); | 2187 | lisp_free (b); |
| 2192 | string_free_list = free_list_before; | 2188 | string_free_list = free_list_before; |
| 2193 | } | 2189 | } |
| 2194 | else | 2190 | else |
| 2195 | { | 2191 | { |
| 2196 | total_free_strings += nfree; | 2192 | gcstat.total_free_strings += nfree; |
| 2197 | b->next = live_blocks; | 2193 | b->next = live_blocks; |
| 2198 | live_blocks = b; | 2194 | live_blocks = b; |
| 2199 | } | 2195 | } |
| @@ -2701,7 +2697,7 @@ make_float (double float_value) | |||
| 2701 | memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); | 2697 | memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); |
| 2702 | float_block = new; | 2698 | float_block = new; |
| 2703 | float_block_index = 0; | 2699 | float_block_index = 0; |
| 2704 | total_free_floats += FLOAT_BLOCK_SIZE; | 2700 | gcstat.total_free_floats += FLOAT_BLOCK_SIZE; |
| 2705 | } | 2701 | } |
| 2706 | XSETFLOAT (val, &float_block->floats[float_block_index]); | 2702 | XSETFLOAT (val, &float_block->floats[float_block_index]); |
| 2707 | float_block_index++; | 2703 | float_block_index++; |
| @@ -2713,7 +2709,7 @@ make_float (double float_value) | |||
| 2713 | eassert (!XFLOAT_MARKED_P (XFLOAT (val))); | 2709 | eassert (!XFLOAT_MARKED_P (XFLOAT (val))); |
| 2714 | consing_since_gc += sizeof (struct Lisp_Float); | 2710 | consing_since_gc += sizeof (struct Lisp_Float); |
| 2715 | floats_consed++; | 2711 | floats_consed++; |
| 2716 | total_free_floats--; | 2712 | gcstat.total_free_floats--; |
| 2717 | return val; | 2713 | return val; |
| 2718 | } | 2714 | } |
| 2719 | 2715 | ||
| @@ -2779,7 +2775,7 @@ free_cons (struct Lisp_Cons *ptr) | |||
| 2779 | ptr->u.s.car = Vdead; | 2775 | ptr->u.s.car = Vdead; |
| 2780 | cons_free_list = ptr; | 2776 | cons_free_list = ptr; |
| 2781 | consing_since_gc -= sizeof *ptr; | 2777 | consing_since_gc -= sizeof *ptr; |
| 2782 | total_free_conses++; | 2778 | gcstat.total_free_conses++; |
| 2783 | } | 2779 | } |
| 2784 | 2780 | ||
| 2785 | DEFUN ("cons", Fcons, Scons, 2, 2, 0, | 2781 | DEFUN ("cons", Fcons, Scons, 2, 2, 0, |
| @@ -2809,7 +2805,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 2809 | distinct conses might not fit. */ | 2805 | distinct conses might not fit. */ |
| 2810 | if (max_conses < INTPTR_MAX / sizeof (struct Lisp_Cons) | 2806 | if (max_conses < INTPTR_MAX / sizeof (struct Lisp_Cons) |
| 2811 | && (max_conses - CONS_BLOCK_SIZE | 2807 | && (max_conses - CONS_BLOCK_SIZE |
| 2812 | < total_free_conses + total_conses)) | 2808 | < gcstat.total_free_conses + gcstat.total_conses)) |
| 2813 | memory_full (sizeof (struct cons_block)); | 2809 | memory_full (sizeof (struct cons_block)); |
| 2814 | 2810 | ||
| 2815 | struct cons_block *new | 2811 | struct cons_block *new |
| @@ -2818,7 +2814,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 2818 | new->next = cons_block; | 2814 | new->next = cons_block; |
| 2819 | cons_block = new; | 2815 | cons_block = new; |
| 2820 | cons_block_index = 0; | 2816 | cons_block_index = 0; |
| 2821 | total_free_conses += CONS_BLOCK_SIZE; | 2817 | gcstat.total_free_conses += CONS_BLOCK_SIZE; |
| 2822 | } | 2818 | } |
| 2823 | XSETCONS (val, &cons_block->conses[cons_block_index]); | 2819 | XSETCONS (val, &cons_block->conses[cons_block_index]); |
| 2824 | cons_block_index++; | 2820 | cons_block_index++; |
| @@ -2830,7 +2826,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 2830 | XSETCDR (val, cdr); | 2826 | XSETCDR (val, cdr); |
| 2831 | eassert (!XCONS_MARKED_P (XCONS (val))); | 2827 | eassert (!XCONS_MARKED_P (XCONS (val))); |
| 2832 | consing_since_gc += sizeof (struct Lisp_Cons); | 2828 | consing_since_gc += sizeof (struct Lisp_Cons); |
| 2833 | total_free_conses--; | 2829 | gcstat.total_free_conses--; |
| 2834 | cons_cells_consed++; | 2830 | cons_cells_consed++; |
| 2835 | return val; | 2831 | return val; |
| 2836 | } | 2832 | } |
| @@ -3080,14 +3076,6 @@ static struct large_vector *large_vectors; | |||
| 3080 | 3076 | ||
| 3081 | Lisp_Object zero_vector; | 3077 | Lisp_Object zero_vector; |
| 3082 | 3078 | ||
| 3083 | /* Number of live vectors. */ | ||
| 3084 | |||
| 3085 | static object_ct total_vectors; | ||
| 3086 | |||
| 3087 | /* Total size of live and free vectors, in Lisp_Object units. */ | ||
| 3088 | |||
| 3089 | static object_ct total_vector_slots, total_free_vector_slots; | ||
| 3090 | |||
| 3091 | /* Common shortcut to setup vector on a free list. */ | 3079 | /* Common shortcut to setup vector on a free list. */ |
| 3092 | 3080 | ||
| 3093 | static void | 3081 | static void |
| @@ -3102,7 +3090,7 @@ setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes) | |||
| 3102 | eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX); | 3090 | eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX); |
| 3103 | set_next_vector (v, vector_free_lists[vindex]); | 3091 | set_next_vector (v, vector_free_lists[vindex]); |
| 3104 | vector_free_lists[vindex] = v; | 3092 | vector_free_lists[vindex] = v; |
| 3105 | total_free_vector_slots += nbytes / word_size; | 3093 | gcstat.total_free_vector_slots += nbytes / word_size; |
| 3106 | } | 3094 | } |
| 3107 | 3095 | ||
| 3108 | /* Get a new vector block. */ | 3096 | /* Get a new vector block. */ |
| @@ -3150,7 +3138,7 @@ allocate_vector_from_block (ptrdiff_t nbytes) | |||
| 3150 | { | 3138 | { |
| 3151 | vector = vector_free_lists[index]; | 3139 | vector = vector_free_lists[index]; |
| 3152 | vector_free_lists[index] = next_vector (vector); | 3140 | vector_free_lists[index] = next_vector (vector); |
| 3153 | total_free_vector_slots -= nbytes / word_size; | 3141 | gcstat.total_free_vector_slots -= nbytes / word_size; |
| 3154 | return vector; | 3142 | return vector; |
| 3155 | } | 3143 | } |
| 3156 | 3144 | ||
| @@ -3164,7 +3152,7 @@ allocate_vector_from_block (ptrdiff_t nbytes) | |||
| 3164 | /* This vector is larger than requested. */ | 3152 | /* This vector is larger than requested. */ |
| 3165 | vector = vector_free_lists[index]; | 3153 | vector = vector_free_lists[index]; |
| 3166 | vector_free_lists[index] = next_vector (vector); | 3154 | vector_free_lists[index] = next_vector (vector); |
| 3167 | total_free_vector_slots -= nbytes / word_size; | 3155 | gcstat.total_free_vector_slots -= nbytes / word_size; |
| 3168 | 3156 | ||
| 3169 | /* Excess bytes are used for the smaller vector, | 3157 | /* Excess bytes are used for the smaller vector, |
| 3170 | which should be set on an appropriate free list. */ | 3158 | which should be set on an appropriate free list. */ |
| @@ -3295,7 +3283,8 @@ sweep_vectors (void) | |||
| 3295 | struct large_vector *lv, **lvprev = &large_vectors; | 3283 | struct large_vector *lv, **lvprev = &large_vectors; |
| 3296 | struct Lisp_Vector *vector, *next; | 3284 | struct Lisp_Vector *vector, *next; |
| 3297 | 3285 | ||
| 3298 | total_vectors = total_vector_slots = total_free_vector_slots = 0; | 3286 | gcstat.total_vectors = 0; |
| 3287 | gcstat.total_vector_slots = gcstat.total_free_vector_slots = 0; | ||
| 3299 | memset (vector_free_lists, 0, sizeof (vector_free_lists)); | 3288 | memset (vector_free_lists, 0, sizeof (vector_free_lists)); |
| 3300 | 3289 | ||
| 3301 | /* Looking through vector blocks. */ | 3290 | /* Looking through vector blocks. */ |
| @@ -3310,9 +3299,9 @@ sweep_vectors (void) | |||
| 3310 | if (XVECTOR_MARKED_P (vector)) | 3299 | if (XVECTOR_MARKED_P (vector)) |
| 3311 | { | 3300 | { |
| 3312 | XUNMARK_VECTOR (vector); | 3301 | XUNMARK_VECTOR (vector); |
| 3313 | total_vectors++; | 3302 | gcstat.total_vectors++; |
| 3314 | ptrdiff_t nbytes = vector_nbytes (vector); | 3303 | ptrdiff_t nbytes = vector_nbytes (vector); |
| 3315 | total_vector_slots += nbytes / word_size; | 3304 | gcstat.total_vector_slots += nbytes / word_size; |
| 3316 | next = ADVANCE (vector, nbytes); | 3305 | next = ADVANCE (vector, nbytes); |
| 3317 | } | 3306 | } |
| 3318 | else | 3307 | else |
| @@ -3364,12 +3353,11 @@ sweep_vectors (void) | |||
| 3364 | if (XVECTOR_MARKED_P (vector)) | 3353 | if (XVECTOR_MARKED_P (vector)) |
| 3365 | { | 3354 | { |
| 3366 | XUNMARK_VECTOR (vector); | 3355 | XUNMARK_VECTOR (vector); |
| 3367 | total_vectors++; | 3356 | gcstat.total_vectors++; |
| 3368 | if (vector->header.size & PSEUDOVECTOR_FLAG) | 3357 | gcstat.total_vector_slots |
| 3369 | total_vector_slots += vector_nbytes (vector) / word_size; | 3358 | += (vector->header.size & PSEUDOVECTOR_FLAG |
| 3370 | else | 3359 | ? vector_nbytes (vector) / word_size |
| 3371 | total_vector_slots | 3360 | : header_size / word_size + vector->header.size); |
| 3372 | += header_size / word_size + vector->header.size; | ||
| 3373 | lvprev = &lv->next; | 3361 | lvprev = &lv->next; |
| 3374 | } | 3362 | } |
| 3375 | else | 3363 | else |
| @@ -3703,7 +3691,7 @@ Its value is void, and its function definition and property list are nil. */) | |||
| 3703 | new->next = symbol_block; | 3691 | new->next = symbol_block; |
| 3704 | symbol_block = new; | 3692 | symbol_block = new; |
| 3705 | symbol_block_index = 0; | 3693 | symbol_block_index = 0; |
| 3706 | total_free_symbols += SYMBOL_BLOCK_SIZE; | 3694 | gcstat.total_free_symbols += SYMBOL_BLOCK_SIZE; |
| 3707 | } | 3695 | } |
| 3708 | XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]); | 3696 | XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]); |
| 3709 | symbol_block_index++; | 3697 | symbol_block_index++; |
| @@ -3714,7 +3702,7 @@ Its value is void, and its function definition and property list are nil. */) | |||
| 3714 | init_symbol (val, name); | 3702 | init_symbol (val, name); |
| 3715 | consing_since_gc += sizeof (struct Lisp_Symbol); | 3703 | consing_since_gc += sizeof (struct Lisp_Symbol); |
| 3716 | symbols_consed++; | 3704 | symbols_consed++; |
| 3717 | total_free_symbols--; | 3705 | gcstat.total_free_symbols--; |
| 3718 | return val; | 3706 | return val; |
| 3719 | } | 3707 | } |
| 3720 | 3708 | ||
| @@ -4976,7 +4964,7 @@ mark_memory (void *start, void *end) | |||
| 4976 | { | 4964 | { |
| 4977 | Lisp_Object obj = build_string ("test"); | 4965 | Lisp_Object obj = build_string ("test"); |
| 4978 | struct Lisp_String *s = XSTRING (obj); | 4966 | struct Lisp_String *s = XSTRING (obj); |
| 4979 | Fgarbage_collect (); | 4967 | garbage_collect (); |
| 4980 | fprintf (stderr, "test '%s'\n", s->u.s.data); | 4968 | fprintf (stderr, "test '%s'\n", s->u.s.data); |
| 4981 | return Qnil; | 4969 | return Qnil; |
| 4982 | } | 4970 | } |
| @@ -5774,13 +5762,13 @@ static byte_ct | |||
| 5774 | total_bytes_of_live_objects (void) | 5762 | total_bytes_of_live_objects (void) |
| 5775 | { | 5763 | { |
| 5776 | byte_ct tot = 0; | 5764 | byte_ct tot = 0; |
| 5777 | tot += object_bytes (total_conses, sizeof (struct Lisp_Cons)); | 5765 | tot += object_bytes (gcstat.total_conses, sizeof (struct Lisp_Cons)); |
| 5778 | tot += object_bytes (total_symbols, sizeof (struct Lisp_Symbol)); | 5766 | tot += object_bytes (gcstat.total_symbols, sizeof (struct Lisp_Symbol)); |
| 5779 | tot += total_string_bytes; | 5767 | tot += gcstat.total_string_bytes; |
| 5780 | tot += object_bytes (total_vector_slots, word_size); | 5768 | tot += object_bytes (gcstat.total_vector_slots, word_size); |
| 5781 | tot += object_bytes (total_floats, sizeof (struct Lisp_Float)); | 5769 | tot += object_bytes (gcstat.total_floats, sizeof (struct Lisp_Float)); |
| 5782 | tot += object_bytes (total_intervals, sizeof (struct interval)); | 5770 | tot += object_bytes (gcstat.total_intervals, sizeof (struct interval)); |
| 5783 | tot += object_bytes (total_strings, sizeof (struct Lisp_String)); | 5771 | tot += object_bytes (gcstat.total_strings, sizeof (struct Lisp_String)); |
| 5784 | return tot; | 5772 | return tot; |
| 5785 | } | 5773 | } |
| 5786 | 5774 | ||
| @@ -6029,22 +6017,15 @@ mark_and_sweep_weak_table_contents (void) | |||
| 6029 | } | 6017 | } |
| 6030 | } | 6018 | } |
| 6031 | 6019 | ||
| 6032 | /* Subroutine of Fgarbage_collect that does most of the work. It is a | 6020 | /* Subroutine of Fgarbage_collect that does most of the work. */ |
| 6033 | separate function so that we could limit mark_stack in searching | 6021 | static bool |
| 6034 | the stack frames below this function, thus avoiding the rare cases | 6022 | garbage_collect_1 (struct gcstat *gcst) |
| 6035 | where mark_stack finds values that look like live Lisp objects on | ||
| 6036 | portions of stack that couldn't possibly contain such live objects. | ||
| 6037 | For more details of this, see the discussion at | ||
| 6038 | https://lists.gnu.org/r/emacs-devel/2014-05/msg00270.html. */ | ||
| 6039 | static Lisp_Object | ||
| 6040 | garbage_collect_1 (void *end) | ||
| 6041 | { | 6023 | { |
| 6042 | struct buffer *nextb; | 6024 | struct buffer *nextb; |
| 6043 | char stack_top_variable; | 6025 | char stack_top_variable; |
| 6044 | bool message_p; | 6026 | bool message_p; |
| 6045 | ptrdiff_t count = SPECPDL_INDEX (); | 6027 | ptrdiff_t count = SPECPDL_INDEX (); |
| 6046 | struct timespec start; | 6028 | struct timespec start; |
| 6047 | Lisp_Object retval = Qnil; | ||
| 6048 | byte_ct tot_before = 0; | 6029 | byte_ct tot_before = 0; |
| 6049 | 6030 | ||
| 6050 | eassert (weak_hash_tables == NULL); | 6031 | eassert (weak_hash_tables == NULL); |
| @@ -6052,7 +6033,7 @@ garbage_collect_1 (void *end) | |||
| 6052 | /* Can't GC if pure storage overflowed because we can't determine | 6033 | /* Can't GC if pure storage overflowed because we can't determine |
| 6053 | if something is a pure object or not. */ | 6034 | if something is a pure object or not. */ |
| 6054 | if (pure_bytes_used_before_overflow) | 6035 | if (pure_bytes_used_before_overflow) |
| 6055 | return Qnil; | 6036 | return false; |
| 6056 | 6037 | ||
| 6057 | /* Record this function, so it appears on the profiler's backtraces. */ | 6038 | /* Record this function, so it appears on the profiler's backtraces. */ |
| 6058 | record_in_backtrace (QAutomatic_GC, 0, 0); | 6039 | record_in_backtrace (QAutomatic_GC, 0, 0); |
| @@ -6215,40 +6196,7 @@ garbage_collect_1 (void *end) | |||
| 6215 | 6196 | ||
| 6216 | unbind_to (count, Qnil); | 6197 | unbind_to (count, Qnil); |
| 6217 | 6198 | ||
| 6218 | Lisp_Object total[] = { | 6199 | *gcst = gcstat; |
| 6219 | list4 (Qconses, make_fixnum (sizeof (struct Lisp_Cons)), | ||
| 6220 | make_int (total_conses), | ||
| 6221 | make_int (total_free_conses)), | ||
| 6222 | list4 (Qsymbols, make_fixnum (sizeof (struct Lisp_Symbol)), | ||
| 6223 | make_int (total_symbols), | ||
| 6224 | make_int (total_free_symbols)), | ||
| 6225 | list4 (Qstrings, make_fixnum (sizeof (struct Lisp_String)), | ||
| 6226 | make_int (total_strings), | ||
| 6227 | make_int (total_free_strings)), | ||
| 6228 | list3 (Qstring_bytes, make_fixnum (1), | ||
| 6229 | make_int (total_string_bytes)), | ||
| 6230 | list3 (Qvectors, | ||
| 6231 | make_fixnum (header_size + sizeof (Lisp_Object)), | ||
| 6232 | make_int (total_vectors)), | ||
| 6233 | list4 (Qvector_slots, make_fixnum (word_size), | ||
| 6234 | make_int (total_vector_slots), | ||
| 6235 | make_int (total_free_vector_slots)), | ||
| 6236 | list4 (Qfloats, make_fixnum (sizeof (struct Lisp_Float)), | ||
| 6237 | make_int (total_floats), | ||
| 6238 | make_int (total_free_floats)), | ||
| 6239 | list4 (Qintervals, make_fixnum (sizeof (struct interval)), | ||
| 6240 | make_int (total_intervals), | ||
| 6241 | make_int (total_free_intervals)), | ||
| 6242 | list3 (Qbuffers, make_fixnum (sizeof (struct buffer)), | ||
| 6243 | make_int (total_buffers)), | ||
| 6244 | |||
| 6245 | #ifdef DOUG_LEA_MALLOC | ||
| 6246 | list4 (Qheap, make_fixnum (1024), | ||
| 6247 | make_int ((mallinfo ().uordblks + 1023) >> 10), | ||
| 6248 | make_int ((mallinfo ().fordblks + 1023) >> 10)), | ||
| 6249 | #endif | ||
| 6250 | }; | ||
| 6251 | retval = CALLMANY (Flist, total); | ||
| 6252 | 6200 | ||
| 6253 | /* GC is complete: now we can run our finalizer callbacks. */ | 6201 | /* GC is complete: now we can run our finalizer callbacks. */ |
| 6254 | run_finalizers (&doomed_finalizers); | 6202 | run_finalizers (&doomed_finalizers); |
| @@ -6278,7 +6226,14 @@ garbage_collect_1 (void *end) | |||
| 6278 | malloc_probe (min (swept, SIZE_MAX)); | 6226 | malloc_probe (min (swept, SIZE_MAX)); |
| 6279 | } | 6227 | } |
| 6280 | 6228 | ||
| 6281 | return retval; | 6229 | return true; |
| 6230 | } | ||
| 6231 | |||
| 6232 | void | ||
| 6233 | garbage_collect (void) | ||
| 6234 | { | ||
| 6235 | struct gcstat gcst; | ||
| 6236 | garbage_collect_1 (&gcst); | ||
| 6282 | } | 6237 | } |
| 6283 | 6238 | ||
| 6284 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", | 6239 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", |
| @@ -6295,13 +6250,47 @@ where each entry has the form (NAME SIZE USED FREE), where: | |||
| 6295 | to return them to the OS). | 6250 | to return them to the OS). |
| 6296 | However, if there was overflow in pure space, `garbage-collect' | 6251 | However, if there was overflow in pure space, `garbage-collect' |
| 6297 | returns nil, because real GC can't be done. | 6252 | returns nil, because real GC can't be done. |
| 6298 | See Info node `(elisp)Garbage Collection'. */ | 6253 | See Info node `(elisp)Garbage Collection'. */) |
| 6299 | attributes: noinline) | ||
| 6300 | (void) | 6254 | (void) |
| 6301 | { | 6255 | { |
| 6302 | void *end; | 6256 | struct gcstat gcst; |
| 6303 | SET_STACK_TOP_ADDRESS (&end); | 6257 | if (!garbage_collect_1 (&gcst)) |
| 6304 | return garbage_collect_1 (end); | 6258 | return Qnil; |
| 6259 | |||
| 6260 | Lisp_Object total[] = { | ||
| 6261 | list4 (Qconses, make_fixnum (sizeof (struct Lisp_Cons)), | ||
| 6262 | make_int (gcst.total_conses), | ||
| 6263 | make_int (gcst.total_free_conses)), | ||
| 6264 | list4 (Qsymbols, make_fixnum (sizeof (struct Lisp_Symbol)), | ||
| 6265 | make_int (gcst.total_symbols), | ||
| 6266 | make_int (gcst.total_free_symbols)), | ||
| 6267 | list4 (Qstrings, make_fixnum (sizeof (struct Lisp_String)), | ||
| 6268 | make_int (gcst.total_strings), | ||
| 6269 | make_int (gcst.total_free_strings)), | ||
| 6270 | list3 (Qstring_bytes, make_fixnum (1), | ||
| 6271 | make_int (gcst.total_string_bytes)), | ||
| 6272 | list3 (Qvectors, | ||
| 6273 | make_fixnum (header_size + sizeof (Lisp_Object)), | ||
| 6274 | make_int (gcst.total_vectors)), | ||
| 6275 | list4 (Qvector_slots, make_fixnum (word_size), | ||
| 6276 | make_int (gcst.total_vector_slots), | ||
| 6277 | make_int (gcst.total_free_vector_slots)), | ||
| 6278 | list4 (Qfloats, make_fixnum (sizeof (struct Lisp_Float)), | ||
| 6279 | make_int (gcst.total_floats), | ||
| 6280 | make_int (gcst.total_free_floats)), | ||
| 6281 | list4 (Qintervals, make_fixnum (sizeof (struct interval)), | ||
| 6282 | make_int (gcst.total_intervals), | ||
| 6283 | make_int (gcst.total_free_intervals)), | ||
| 6284 | list3 (Qbuffers, make_fixnum (sizeof (struct buffer)), | ||
| 6285 | make_int (gcst.total_buffers)), | ||
| 6286 | |||
| 6287 | #ifdef DOUG_LEA_MALLOC | ||
| 6288 | list4 (Qheap, make_fixnum (1024), | ||
| 6289 | make_int ((mallinfo ().uordblks + 1023) >> 10), | ||
| 6290 | make_int ((mallinfo ().fordblks + 1023) >> 10)), | ||
| 6291 | #endif | ||
| 6292 | }; | ||
| 6293 | return CALLMANY (Flist, total); | ||
| 6305 | } | 6294 | } |
| 6306 | 6295 | ||
| 6307 | /* Mark Lisp objects in glyph matrix MATRIX. Currently the | 6296 | /* Mark Lisp objects in glyph matrix MATRIX. Currently the |
| @@ -7003,8 +6992,8 @@ sweep_conses (void) | |||
| 7003 | cprev = &cblk->next; | 6992 | cprev = &cblk->next; |
| 7004 | } | 6993 | } |
| 7005 | } | 6994 | } |
| 7006 | total_conses = num_used; | 6995 | gcstat.total_conses = num_used; |
| 7007 | total_free_conses = num_free; | 6996 | gcstat.total_free_conses = num_free; |
| 7008 | } | 6997 | } |
| 7009 | 6998 | ||
| 7010 | NO_INLINE /* For better stack traces */ | 6999 | NO_INLINE /* For better stack traces */ |
| @@ -7052,8 +7041,8 @@ sweep_floats (void) | |||
| 7052 | fprev = &fblk->next; | 7041 | fprev = &fblk->next; |
| 7053 | } | 7042 | } |
| 7054 | } | 7043 | } |
| 7055 | total_floats = num_used; | 7044 | gcstat.total_floats = num_used; |
| 7056 | total_free_floats = num_free; | 7045 | gcstat.total_free_floats = num_free; |
| 7057 | } | 7046 | } |
| 7058 | 7047 | ||
| 7059 | NO_INLINE /* For better stack traces */ | 7048 | NO_INLINE /* For better stack traces */ |
| @@ -7101,8 +7090,8 @@ sweep_intervals (void) | |||
| 7101 | iprev = &iblk->next; | 7090 | iprev = &iblk->next; |
| 7102 | } | 7091 | } |
| 7103 | } | 7092 | } |
| 7104 | total_intervals = num_used; | 7093 | gcstat.total_intervals = num_used; |
| 7105 | total_free_intervals = num_free; | 7094 | gcstat.total_free_intervals = num_free; |
| 7106 | } | 7095 | } |
| 7107 | 7096 | ||
| 7108 | NO_INLINE /* For better stack traces */ | 7097 | NO_INLINE /* For better stack traces */ |
| @@ -7170,8 +7159,8 @@ sweep_symbols (void) | |||
| 7170 | sprev = &sblk->next; | 7159 | sprev = &sblk->next; |
| 7171 | } | 7160 | } |
| 7172 | } | 7161 | } |
| 7173 | total_symbols = num_used; | 7162 | gcstat.total_symbols = num_used; |
| 7174 | total_free_symbols = num_free; | 7163 | gcstat.total_free_symbols = num_free; |
| 7175 | } | 7164 | } |
| 7176 | 7165 | ||
| 7177 | /* Remove BUFFER's markers that are due to be swept. This is needed since | 7166 | /* Remove BUFFER's markers that are due to be swept. This is needed since |
| @@ -7195,9 +7184,9 @@ NO_INLINE /* For better stack traces */ | |||
| 7195 | static void | 7184 | static void |
| 7196 | sweep_buffers (void) | 7185 | sweep_buffers (void) |
| 7197 | { | 7186 | { |
| 7198 | register struct buffer *buffer, **bprev = &all_buffers; | 7187 | struct buffer *buffer, **bprev = &all_buffers; |
| 7199 | 7188 | ||
| 7200 | total_buffers = 0; | 7189 | gcstat.total_buffers = 0; |
| 7201 | for (buffer = all_buffers; buffer; buffer = *bprev) | 7190 | for (buffer = all_buffers; buffer; buffer = *bprev) |
| 7202 | if (!vectorlike_marked_p (&buffer->header)) | 7191 | if (!vectorlike_marked_p (&buffer->header)) |
| 7203 | { | 7192 | { |
| @@ -7211,7 +7200,7 @@ sweep_buffers (void) | |||
| 7211 | /* Do not use buffer_(set|get)_intervals here. */ | 7200 | /* Do not use buffer_(set|get)_intervals here. */ |
| 7212 | buffer->text->intervals = balance_intervals (buffer->text->intervals); | 7201 | buffer->text->intervals = balance_intervals (buffer->text->intervals); |
| 7213 | unchain_dead_markers (buffer); | 7202 | unchain_dead_markers (buffer); |
| 7214 | total_buffers++; | 7203 | gcstat.total_buffers++; |
| 7215 | bprev = &buffer->next; | 7204 | bprev = &buffer->next; |
| 7216 | } | 7205 | } |
| 7217 | } | 7206 | } |
diff --git a/src/lisp.h b/src/lisp.h index 388cd04163a..32576930b29 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3763,6 +3763,7 @@ extern void alloc_unexec_post (void); | |||
| 3763 | extern void mark_maybe_objects (Lisp_Object *, ptrdiff_t); | 3763 | extern void mark_maybe_objects (Lisp_Object *, ptrdiff_t); |
| 3764 | extern void mark_stack (char *, char *); | 3764 | extern void mark_stack (char *, char *); |
| 3765 | extern void flush_stack_call_func (void (*func) (void *arg), void *arg); | 3765 | extern void flush_stack_call_func (void (*func) (void *arg), void *arg); |
| 3766 | extern void garbage_collect (void); | ||
| 3766 | extern const char *pending_malloc_warning; | 3767 | extern const char *pending_malloc_warning; |
| 3767 | extern Lisp_Object zero_vector; | 3768 | extern Lisp_Object zero_vector; |
| 3768 | typedef uintptr_t byte_ct; /* System byte counts reported by GC. */ | 3769 | typedef uintptr_t byte_ct; /* System byte counts reported by GC. */ |
| @@ -5003,7 +5004,7 @@ maybe_gc (void) | |||
| 5003 | && consing_since_gc > gc_relative_threshold) | 5004 | && consing_since_gc > gc_relative_threshold) |
| 5004 | || (!NILP (Vmemory_full) | 5005 | || (!NILP (Vmemory_full) |
| 5005 | && consing_since_gc > memory_full_cons_threshold)) | 5006 | && consing_since_gc > memory_full_cons_threshold)) |
| 5006 | Fgarbage_collect (); | 5007 | garbage_collect (); |
| 5007 | } | 5008 | } |
| 5008 | 5009 | ||
| 5009 | INLINE_HEADER_END | 5010 | INLINE_HEADER_END |
diff --git a/src/pdumper.c b/src/pdumper.c index 724ea7be6d0..4d35fd1233f 100644 --- a/src/pdumper.c +++ b/src/pdumper.c | |||
| @@ -4055,7 +4055,7 @@ types. */) | |||
| 4055 | /* Clear out any detritus in memory. */ | 4055 | /* Clear out any detritus in memory. */ |
| 4056 | do { | 4056 | do { |
| 4057 | number_finalizers_run = 0; | 4057 | number_finalizers_run = 0; |
| 4058 | Fgarbage_collect (); | 4058 | garbage_collect (); |
| 4059 | } while (number_finalizers_run); | 4059 | } while (number_finalizers_run); |
| 4060 | 4060 | ||
| 4061 | ptrdiff_t count = SPECPDL_INDEX (); | 4061 | ptrdiff_t count = SPECPDL_INDEX (); |