aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2019-03-01 09:01:59 -0800
committerPaul Eggert2019-03-01 09:09:47 -0800
commit7e29eae023c8158d41eba02c2367e70cbee53642 (patch)
tree6679f45eba3b0b06dfb8ba4353b259445b6c1340 /src
parentfb52d961a40d889d87628058be6ea8116ced2e13 (diff)
downloademacs-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.c237
-rw-r--r--src/lisp.h3
-rw-r--r--src/pdumper.c2
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
256static object_ct total_conses, total_symbols, total_buffers; 256struct gcstat
257static object_ct total_free_conses, total_free_symbols; 257{
258static 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
1539static int interval_block_index = INTERVAL_BLOCK_SIZE; 1547static int interval_block_index = INTERVAL_BLOCK_SIZE;
1540 1548
1541/* Number of free and live intervals. */
1542
1543static object_ct total_free_intervals, total_intervals;
1544
1545/* List of free intervals. */ 1549/* List of free intervals. */
1546 1550
1547static INTERVAL interval_free_list; 1551static 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
1756static struct Lisp_String *string_free_list; 1760static struct Lisp_String *string_free_list;
1757 1761
1758/* Number of live and free Lisp_Strings. */
1759
1760static object_ct total_strings, total_free_strings;
1761
1762/* Number of bytes used by live strings. */
1763
1764static 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
2785DEFUN ("cons", Fcons, Scons, 2, 2, 0, 2781DEFUN ("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
3081Lisp_Object zero_vector; 3077Lisp_Object zero_vector;
3082 3078
3083/* Number of live vectors. */
3084
3085static object_ct total_vectors;
3086
3087/* Total size of live and free vectors, in Lisp_Object units. */
3088
3089static 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
3093static void 3081static 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
5774total_bytes_of_live_objects (void) 5762total_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 6021static bool
6034 the stack frames below this function, thus avoiding the rare cases 6022garbage_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. */
6039static Lisp_Object
6040garbage_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
6232void
6233garbage_collect (void)
6234{
6235 struct gcstat gcst;
6236 garbage_collect_1 (&gcst);
6282} 6237}
6283 6238
6284DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", 6239DEFUN ("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).
6296However, if there was overflow in pure space, `garbage-collect' 6251However, if there was overflow in pure space, `garbage-collect'
6297returns nil, because real GC can't be done. 6252returns nil, because real GC can't be done.
6298See Info node `(elisp)Garbage Collection'. */ 6253See 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
7010NO_INLINE /* For better stack traces */ 6999NO_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
7059NO_INLINE /* For better stack traces */ 7048NO_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
7108NO_INLINE /* For better stack traces */ 7097NO_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 */
7195static void 7184static void
7196sweep_buffers (void) 7185sweep_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);
3763extern void mark_maybe_objects (Lisp_Object *, ptrdiff_t); 3763extern void mark_maybe_objects (Lisp_Object *, ptrdiff_t);
3764extern void mark_stack (char *, char *); 3764extern void mark_stack (char *, char *);
3765extern void flush_stack_call_func (void (*func) (void *arg), void *arg); 3765extern void flush_stack_call_func (void (*func) (void *arg), void *arg);
3766extern void garbage_collect (void);
3766extern const char *pending_malloc_warning; 3767extern const char *pending_malloc_warning;
3767extern Lisp_Object zero_vector; 3768extern Lisp_Object zero_vector;
3768typedef uintptr_t byte_ct; /* System byte counts reported by GC. */ 3769typedef 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
5009INLINE_HEADER_END 5010INLINE_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 ();