diff options
| author | Paul Eggert | 2019-09-13 16:09:48 -0700 |
|---|---|---|
| committer | Paul Eggert | 2019-09-13 16:10:54 -0700 |
| commit | e4fb98b542c57fa4856fbeb14230ace34d910117 (patch) | |
| tree | 699813b8e331f5d2fc9f79e15d6e0f97a27e9d19 /src | |
| parent | 0dba340da54f129750096a5a8704805a94f5535c (diff) | |
| download | emacs-e4fb98b542c57fa4856fbeb14230ace34d910117.tar.gz emacs-e4fb98b542c57fa4856fbeb14230ace34d910117.zip | |
Simplify GC statistics-gathering
* src/alloc.c (make_interval, allocate_string, make_float)
(free_cons, Fcons, setup_on_free_list)
(allocate_vector_from_block, Fmake_symbol):
Do not update gcstat, since it is for statistics from the most
recent GC, not for a partially-updated hodgepodge.
(sweep_vectors): Update gcstat, since setup_on_free_list
no longer does.
(garbage_collect_1): Rename to garbage_collect and adopt its API.
Remove the old garbage_collect, which is no longer needed.
All callers changed.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 66 |
1 files changed, 15 insertions, 51 deletions
diff --git a/src/alloc.c b/src/alloc.c index 2d490f3bb75..ca8311cc00a 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -241,7 +241,7 @@ bool gc_in_progress; | |||
| 241 | typedef uintptr_t byte_ct; | 241 | typedef uintptr_t byte_ct; |
| 242 | typedef intptr_t object_ct; | 242 | typedef intptr_t object_ct; |
| 243 | 243 | ||
| 244 | /* Number of live and free conses etc. */ | 244 | /* Number of live and free conses etc. counted by the most-recent GC. */ |
| 245 | 245 | ||
| 246 | static struct gcstat | 246 | static struct gcstat |
| 247 | { | 247 | { |
| @@ -560,7 +560,7 @@ struct Lisp_Finalizer finalizers; | |||
| 560 | 560 | ||
| 561 | /* Head of a circularly-linked list of finalizers that must be invoked | 561 | /* Head of a circularly-linked list of finalizers that must be invoked |
| 562 | because we deemed them unreachable. This list must be global, and | 562 | because we deemed them unreachable. This list must be global, and |
| 563 | not a local inside garbage_collect_1, in case we GC again while | 563 | not a local inside garbage_collect, in case we GC again while |
| 564 | running finalizers. */ | 564 | running finalizers. */ |
| 565 | struct Lisp_Finalizer doomed_finalizers; | 565 | struct Lisp_Finalizer doomed_finalizers; |
| 566 | 566 | ||
| @@ -1366,7 +1366,6 @@ make_interval (void) | |||
| 1366 | newi->next = interval_block; | 1366 | newi->next = interval_block; |
| 1367 | interval_block = newi; | 1367 | interval_block = newi; |
| 1368 | interval_block_index = 0; | 1368 | interval_block_index = 0; |
| 1369 | gcstat.total_free_intervals += INTERVAL_BLOCK_SIZE; | ||
| 1370 | } | 1369 | } |
| 1371 | val = &interval_block->intervals[interval_block_index++]; | 1370 | val = &interval_block->intervals[interval_block_index++]; |
| 1372 | } | 1371 | } |
| @@ -1375,7 +1374,6 @@ make_interval (void) | |||
| 1375 | 1374 | ||
| 1376 | consing_until_gc -= sizeof (struct interval); | 1375 | consing_until_gc -= sizeof (struct interval); |
| 1377 | intervals_consed++; | 1376 | intervals_consed++; |
| 1378 | gcstat.total_free_intervals--; | ||
| 1379 | RESET_INTERVAL (val); | 1377 | RESET_INTERVAL (val); |
| 1380 | val->gcmarkbit = 0; | 1378 | val->gcmarkbit = 0; |
| 1381 | return val; | 1379 | return val; |
| @@ -1730,8 +1728,6 @@ allocate_string (void) | |||
| 1730 | NEXT_FREE_LISP_STRING (s) = string_free_list; | 1728 | NEXT_FREE_LISP_STRING (s) = string_free_list; |
| 1731 | string_free_list = ptr_bounds_clip (s, sizeof *s); | 1729 | string_free_list = ptr_bounds_clip (s, sizeof *s); |
| 1732 | } | 1730 | } |
| 1733 | |||
| 1734 | gcstat.total_free_strings += STRING_BLOCK_SIZE; | ||
| 1735 | } | 1731 | } |
| 1736 | 1732 | ||
| 1737 | check_string_free_list (); | 1733 | check_string_free_list (); |
| @@ -1742,8 +1738,6 @@ allocate_string (void) | |||
| 1742 | 1738 | ||
| 1743 | MALLOC_UNBLOCK_INPUT; | 1739 | MALLOC_UNBLOCK_INPUT; |
| 1744 | 1740 | ||
| 1745 | gcstat.total_free_strings--; | ||
| 1746 | gcstat.total_strings++; | ||
| 1747 | ++strings_consed; | 1741 | ++strings_consed; |
| 1748 | consing_until_gc -= sizeof *s; | 1742 | consing_until_gc -= sizeof *s; |
| 1749 | 1743 | ||
| @@ -2461,7 +2455,6 @@ make_float (double float_value) | |||
| 2461 | memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); | 2455 | memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); |
| 2462 | float_block = new; | 2456 | float_block = new; |
| 2463 | float_block_index = 0; | 2457 | float_block_index = 0; |
| 2464 | gcstat.total_free_floats += FLOAT_BLOCK_SIZE; | ||
| 2465 | } | 2458 | } |
| 2466 | XSETFLOAT (val, &float_block->floats[float_block_index]); | 2459 | XSETFLOAT (val, &float_block->floats[float_block_index]); |
| 2467 | float_block_index++; | 2460 | float_block_index++; |
| @@ -2473,7 +2466,6 @@ make_float (double float_value) | |||
| 2473 | eassert (!XFLOAT_MARKED_P (XFLOAT (val))); | 2466 | eassert (!XFLOAT_MARKED_P (XFLOAT (val))); |
| 2474 | consing_until_gc -= sizeof (struct Lisp_Float); | 2467 | consing_until_gc -= sizeof (struct Lisp_Float); |
| 2475 | floats_consed++; | 2468 | floats_consed++; |
| 2476 | gcstat.total_free_floats--; | ||
| 2477 | return val; | 2469 | return val; |
| 2478 | } | 2470 | } |
| 2479 | 2471 | ||
| @@ -2545,7 +2537,6 @@ free_cons (struct Lisp_Cons *ptr) | |||
| 2545 | cons_free_list = ptr; | 2537 | cons_free_list = ptr; |
| 2546 | if (INT_ADD_WRAPV (consing_until_gc, sizeof *ptr, &consing_until_gc)) | 2538 | if (INT_ADD_WRAPV (consing_until_gc, sizeof *ptr, &consing_until_gc)) |
| 2547 | consing_until_gc = INTMAX_MAX; | 2539 | consing_until_gc = INTMAX_MAX; |
| 2548 | gcstat.total_free_conses++; | ||
| 2549 | } | 2540 | } |
| 2550 | 2541 | ||
| 2551 | DEFUN ("cons", Fcons, Scons, 2, 2, 0, | 2542 | DEFUN ("cons", Fcons, Scons, 2, 2, 0, |
| @@ -2565,26 +2556,12 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 2565 | { | 2556 | { |
| 2566 | if (cons_block_index == CONS_BLOCK_SIZE) | 2557 | if (cons_block_index == CONS_BLOCK_SIZE) |
| 2567 | { | 2558 | { |
| 2568 | /* Maximum number of conses that should be active at any | ||
| 2569 | given time, so that list lengths fit into a ptrdiff_t and | ||
| 2570 | into a fixnum. */ | ||
| 2571 | ptrdiff_t max_conses = min (PTRDIFF_MAX, MOST_POSITIVE_FIXNUM); | ||
| 2572 | |||
| 2573 | /* This check is typically optimized away, as a runtime | ||
| 2574 | check is needed only on weird platforms where a count of | ||
| 2575 | distinct conses might not fit. */ | ||
| 2576 | if (max_conses < INTPTR_MAX / sizeof (struct Lisp_Cons) | ||
| 2577 | && (max_conses - CONS_BLOCK_SIZE | ||
| 2578 | < gcstat.total_free_conses + gcstat.total_conses)) | ||
| 2579 | memory_full (sizeof (struct cons_block)); | ||
| 2580 | |||
| 2581 | struct cons_block *new | 2559 | struct cons_block *new |
| 2582 | = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS); | 2560 | = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS); |
| 2583 | memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); | 2561 | memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); |
| 2584 | new->next = cons_block; | 2562 | new->next = cons_block; |
| 2585 | cons_block = new; | 2563 | cons_block = new; |
| 2586 | cons_block_index = 0; | 2564 | cons_block_index = 0; |
| 2587 | gcstat.total_free_conses += CONS_BLOCK_SIZE; | ||
| 2588 | } | 2565 | } |
| 2589 | XSETCONS (val, &cons_block->conses[cons_block_index]); | 2566 | XSETCONS (val, &cons_block->conses[cons_block_index]); |
| 2590 | cons_block_index++; | 2567 | cons_block_index++; |
| @@ -2596,7 +2573,6 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 2596 | XSETCDR (val, cdr); | 2573 | XSETCDR (val, cdr); |
| 2597 | eassert (!XCONS_MARKED_P (XCONS (val))); | 2574 | eassert (!XCONS_MARKED_P (XCONS (val))); |
| 2598 | consing_until_gc -= sizeof (struct Lisp_Cons); | 2575 | consing_until_gc -= sizeof (struct Lisp_Cons); |
| 2599 | gcstat.total_free_conses--; | ||
| 2600 | cons_cells_consed++; | 2576 | cons_cells_consed++; |
| 2601 | return val; | 2577 | return val; |
| 2602 | } | 2578 | } |
| @@ -2855,7 +2831,6 @@ setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes) | |||
| 2855 | eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX); | 2831 | eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX); |
| 2856 | set_next_vector (v, vector_free_lists[vindex]); | 2832 | set_next_vector (v, vector_free_lists[vindex]); |
| 2857 | vector_free_lists[vindex] = v; | 2833 | vector_free_lists[vindex] = v; |
| 2858 | gcstat.total_free_vector_slots += nbytes / word_size; | ||
| 2859 | } | 2834 | } |
| 2860 | 2835 | ||
| 2861 | /* Get a new vector block. */ | 2836 | /* Get a new vector block. */ |
| @@ -2903,7 +2878,6 @@ allocate_vector_from_block (ptrdiff_t nbytes) | |||
| 2903 | { | 2878 | { |
| 2904 | vector = vector_free_lists[index]; | 2879 | vector = vector_free_lists[index]; |
| 2905 | vector_free_lists[index] = next_vector (vector); | 2880 | vector_free_lists[index] = next_vector (vector); |
| 2906 | gcstat.total_free_vector_slots -= nbytes / word_size; | ||
| 2907 | return vector; | 2881 | return vector; |
| 2908 | } | 2882 | } |
| 2909 | 2883 | ||
| @@ -2917,7 +2891,6 @@ allocate_vector_from_block (ptrdiff_t nbytes) | |||
| 2917 | /* This vector is larger than requested. */ | 2891 | /* This vector is larger than requested. */ |
| 2918 | vector = vector_free_lists[index]; | 2892 | vector = vector_free_lists[index]; |
| 2919 | vector_free_lists[index] = next_vector (vector); | 2893 | vector_free_lists[index] = next_vector (vector); |
| 2920 | gcstat.total_free_vector_slots -= nbytes / word_size; | ||
| 2921 | 2894 | ||
| 2922 | /* Excess bytes are used for the smaller vector, | 2895 | /* Excess bytes are used for the smaller vector, |
| 2923 | which should be set on an appropriate free list. */ | 2896 | which should be set on an appropriate free list. */ |
| @@ -3092,7 +3065,10 @@ sweep_vectors (void) | |||
| 3092 | space was coalesced into the only free vector. */ | 3065 | space was coalesced into the only free vector. */ |
| 3093 | free_this_block = true; | 3066 | free_this_block = true; |
| 3094 | else | 3067 | else |
| 3095 | setup_on_free_list (vector, total_bytes); | 3068 | { |
| 3069 | setup_on_free_list (vector, total_bytes); | ||
| 3070 | gcstat.total_free_vector_slots += total_bytes / word_size; | ||
| 3071 | } | ||
| 3096 | } | 3072 | } |
| 3097 | } | 3073 | } |
| 3098 | 3074 | ||
| @@ -3454,7 +3430,6 @@ Its value is void, and its function definition and property list are nil. */) | |||
| 3454 | new->next = symbol_block; | 3430 | new->next = symbol_block; |
| 3455 | symbol_block = new; | 3431 | symbol_block = new; |
| 3456 | symbol_block_index = 0; | 3432 | symbol_block_index = 0; |
| 3457 | gcstat.total_free_symbols += SYMBOL_BLOCK_SIZE; | ||
| 3458 | } | 3433 | } |
| 3459 | XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]); | 3434 | XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]); |
| 3460 | symbol_block_index++; | 3435 | symbol_block_index++; |
| @@ -3465,7 +3440,6 @@ Its value is void, and its function definition and property list are nil. */) | |||
| 3465 | init_symbol (val, name); | 3440 | init_symbol (val, name); |
| 3466 | consing_until_gc -= sizeof (struct Lisp_Symbol); | 3441 | consing_until_gc -= sizeof (struct Lisp_Symbol); |
| 3467 | symbols_consed++; | 3442 | symbols_consed++; |
| 3468 | gcstat.total_free_symbols--; | ||
| 3469 | return val; | 3443 | return val; |
| 3470 | } | 3444 | } |
| 3471 | 3445 | ||
| @@ -5723,7 +5697,7 @@ visit_buffer_root (struct gc_root_visitor visitor, | |||
| 5723 | 5697 | ||
| 5724 | There are other GC roots of course, but these roots are dynamic | 5698 | There are other GC roots of course, but these roots are dynamic |
| 5725 | runtime data structures that pdump doesn't care about and so we can | 5699 | runtime data structures that pdump doesn't care about and so we can |
| 5726 | continue to mark those directly in garbage_collect_1. */ | 5700 | continue to mark those directly in garbage_collect. */ |
| 5727 | void | 5701 | void |
| 5728 | visit_static_gc_roots (struct gc_root_visitor visitor) | 5702 | visit_static_gc_roots (struct gc_root_visitor visitor) |
| 5729 | { | 5703 | { |
| @@ -5753,8 +5727,7 @@ mark_object_root_visitor (Lisp_Object const *root_ptr, | |||
| 5753 | } | 5727 | } |
| 5754 | 5728 | ||
| 5755 | /* List of weak hash tables we found during marking the Lisp heap. | 5729 | /* List of weak hash tables we found during marking the Lisp heap. |
| 5756 | Will be NULL on entry to garbage_collect_1 and after it | 5730 | NULL on entry to garbage_collect and after it returns. */ |
| 5757 | returns. */ | ||
| 5758 | static struct Lisp_Hash_Table *weak_hash_tables; | 5731 | static struct Lisp_Hash_Table *weak_hash_tables; |
| 5759 | 5732 | ||
| 5760 | NO_INLINE /* For better stack traces */ | 5733 | NO_INLINE /* For better stack traces */ |
| @@ -5860,8 +5833,8 @@ watch_gc_cons_percentage (Lisp_Object symbol, Lisp_Object newval, | |||
| 5860 | } | 5833 | } |
| 5861 | 5834 | ||
| 5862 | /* Subroutine of Fgarbage_collect that does most of the work. */ | 5835 | /* Subroutine of Fgarbage_collect that does most of the work. */ |
| 5863 | static bool | 5836 | void |
| 5864 | garbage_collect_1 (struct gcstat *gcst) | 5837 | garbage_collect (void) |
| 5865 | { | 5838 | { |
| 5866 | struct buffer *nextb; | 5839 | struct buffer *nextb; |
| 5867 | char stack_top_variable; | 5840 | char stack_top_variable; |
| @@ -5873,7 +5846,7 @@ garbage_collect_1 (struct gcstat *gcst) | |||
| 5873 | eassert (weak_hash_tables == NULL); | 5846 | eassert (weak_hash_tables == NULL); |
| 5874 | 5847 | ||
| 5875 | if (garbage_collection_inhibited) | 5848 | if (garbage_collection_inhibited) |
| 5876 | return false; | 5849 | return; |
| 5877 | 5850 | ||
| 5878 | /* Record this function, so it appears on the profiler's backtraces. */ | 5851 | /* Record this function, so it appears on the profiler's backtraces. */ |
| 5879 | record_in_backtrace (QAutomatic_GC, 0, 0); | 5852 | record_in_backtrace (QAutomatic_GC, 0, 0); |
| @@ -6014,8 +5987,6 @@ garbage_collect_1 (struct gcstat *gcst) | |||
| 6014 | 5987 | ||
| 6015 | unbind_to (count, Qnil); | 5988 | unbind_to (count, Qnil); |
| 6016 | 5989 | ||
| 6017 | *gcst = gcstat; | ||
| 6018 | |||
| 6019 | /* GC is complete: now we can run our finalizer callbacks. */ | 5990 | /* GC is complete: now we can run our finalizer callbacks. */ |
| 6020 | run_finalizers (&doomed_finalizers); | 5991 | run_finalizers (&doomed_finalizers); |
| 6021 | 5992 | ||
| @@ -6043,15 +6014,6 @@ garbage_collect_1 (struct gcstat *gcst) | |||
| 6043 | byte_ct swept = tot_before <= tot_after ? 0 : tot_before - tot_after; | 6014 | byte_ct swept = tot_before <= tot_after ? 0 : tot_before - tot_after; |
| 6044 | malloc_probe (min (swept, SIZE_MAX)); | 6015 | malloc_probe (min (swept, SIZE_MAX)); |
| 6045 | } | 6016 | } |
| 6046 | |||
| 6047 | return true; | ||
| 6048 | } | ||
| 6049 | |||
| 6050 | void | ||
| 6051 | garbage_collect (void) | ||
| 6052 | { | ||
| 6053 | struct gcstat gcst; | ||
| 6054 | garbage_collect_1 (&gcst); | ||
| 6055 | } | 6017 | } |
| 6056 | 6018 | ||
| 6057 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", | 6019 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", |
| @@ -6071,10 +6033,12 @@ returns nil, because real GC can't be done. | |||
| 6071 | See Info node `(elisp)Garbage Collection'. */) | 6033 | See Info node `(elisp)Garbage Collection'. */) |
| 6072 | (void) | 6034 | (void) |
| 6073 | { | 6035 | { |
| 6074 | struct gcstat gcst; | 6036 | if (garbage_collection_inhibited) |
| 6075 | if (!garbage_collect_1 (&gcst)) | ||
| 6076 | return Qnil; | 6037 | return Qnil; |
| 6077 | 6038 | ||
| 6039 | garbage_collect (); | ||
| 6040 | struct gcstat gcst = gcstat; | ||
| 6041 | |||
| 6078 | Lisp_Object total[] = { | 6042 | Lisp_Object total[] = { |
| 6079 | list4 (Qconses, make_fixnum (sizeof (struct Lisp_Cons)), | 6043 | list4 (Qconses, make_fixnum (sizeof (struct Lisp_Cons)), |
| 6080 | make_int (gcst.total_conses), | 6044 | make_int (gcst.total_conses), |