>From 26de2d42d0460c5b193456950a568cb04a29dc00 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 20 Jul 2019 19:40:03 -0700 Subject: [PATCH 3/6] Simplify maybe_gc implementation * src/alloc.c (consing_until_gc): New variable, replacing the combination of consing_since_gc and gc_relative_threshold. All uses changed. (byte_ct): Move decl here from lisp.h. (memory_full_cons_threshold): New an enum constant. (free_cons): Check for integer overflow in statistics calculation. * src/lisp.h (object_ct): Move decl here from alloc.c. (OBJECT_CT_MAX): New macro. (maybe_gc): Simplify accordingly. --- src/alloc.c | 68 ++++++++++++++++++++++++++--------------------------- src/lisp.h | 12 ++++------ 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index 8649d4e0f4..9d18fd918b 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -222,13 +222,9 @@ #define GC_DEFAULT_THRESHOLD (100000 * word_size) /* Global variables. */ struct emacs_globals globals; -/* Number of bytes of consing done since the last gc. */ +/* maybe_gc collects garbage if this goes negative. */ -byte_ct consing_since_gc; - -/* Similar minimum, computed from Vgc_cons_percentage. */ - -byte_ct gc_relative_threshold; +object_ct consing_until_gc; #ifdef HAVE_PDUMPER /* Number of finalizers run: used to loop over GC until we stop @@ -240,10 +236,9 @@ #define GC_DEFAULT_THRESHOLD (100000 * word_size) bool gc_in_progress; -/* Type of object counts reported by GC. Unlike byte_ct, this can be - signed, e.g., it is less than 2**31 on a typical 32-bit machine. */ +/* System byte counts reported by GC. */ -typedef intptr_t object_ct; +typedef uintptr_t byte_ct; /* Number of live and free conses etc. */ @@ -1373,7 +1368,7 @@ make_interval (void) MALLOC_UNBLOCK_INPUT; - consing_since_gc += sizeof (struct interval); + consing_until_gc -= sizeof (struct interval); intervals_consed++; gcstat.total_free_intervals--; RESET_INTERVAL (val); @@ -1745,7 +1740,7 @@ allocate_string (void) gcstat.total_free_strings--; gcstat.total_strings++; ++strings_consed; - consing_since_gc += sizeof *s; + consing_until_gc -= sizeof *s; #ifdef GC_CHECK_STRING_BYTES if (!noninteractive) @@ -1865,7 +1860,7 @@ allocate_string_data (struct Lisp_String *s, old_data->string = NULL; } - consing_since_gc += needed; + consing_until_gc -= needed; } @@ -2471,7 +2466,7 @@ make_float (double float_value) XFLOAT_INIT (val, float_value); eassert (!XFLOAT_MARKED_P (XFLOAT (val))); - consing_since_gc += sizeof (struct Lisp_Float); + consing_until_gc -= sizeof (struct Lisp_Float); floats_consed++; gcstat.total_free_floats--; return val; @@ -2521,7 +2516,7 @@ #define XUNMARK_CONS(fptr) \ /* Minimum number of bytes of consing since GC before next GC, when memory is full. */ -byte_ct const memory_full_cons_threshold = sizeof (struct cons_block); +enum { memory_full_cons_threshold = sizeof (struct cons_block) }; /* Current cons_block. */ @@ -2543,7 +2538,8 @@ free_cons (struct Lisp_Cons *ptr) ptr->u.s.u.chain = cons_free_list; ptr->u.s.car = dead_object (); cons_free_list = ptr; - consing_since_gc -= sizeof *ptr; + if (INT_ADD_WRAPV (consing_until_gc, sizeof *ptr, &consing_until_gc)) + consing_until_gc = OBJECT_CT_MAX; gcstat.total_free_conses++; } @@ -2594,7 +2590,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, XSETCAR (val, car); XSETCDR (val, cdr); eassert (!XCONS_MARKED_P (XCONS (val))); - consing_since_gc += sizeof (struct Lisp_Cons); + consing_until_gc -= sizeof (struct Lisp_Cons); gcstat.total_free_conses--; cons_cells_consed++; return val; @@ -3176,7 +3172,7 @@ allocate_vectorlike (ptrdiff_t len) if (find_suspicious_object_in_range (p, (char *) p + nbytes)) emacs_abort (); - consing_since_gc += nbytes; + consing_until_gc -= nbytes; vector_cells_consed += len; MALLOC_UNBLOCK_INPUT; @@ -3462,7 +3458,7 @@ DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, MALLOC_UNBLOCK_INPUT; init_symbol (val, name); - consing_since_gc += sizeof (struct Lisp_Symbol); + consing_until_gc -= sizeof (struct Lisp_Symbol); symbols_consed++; gcstat.total_free_symbols--; return val; @@ -3862,6 +3858,7 @@ memory_full (size_t nbytes) if (! enough_free_memory) { Vmemory_full = Qt; + consing_until_gc = memory_full_cons_threshold; /* The first time we get here, free the spare memory. */ for (int i = 0; i < ARRAYELTS (spare_memory); i++) @@ -5802,7 +5799,7 @@ garbage_collect_1 (struct gcstat *gcst) /* In case user calls debug_print during GC, don't let that cause a recursive GC. */ - consing_since_gc = 0; + consing_until_gc = OBJECT_CT_MAX; /* Save what's currently displayed in the echo area. Don't do that if we are GC'ing because we've run out of memory, since @@ -5913,23 +5910,26 @@ garbage_collect_1 (struct gcstat *gcst) unblock_input (); - consing_since_gc = 0; - if (gc_cons_threshold < GC_DEFAULT_THRESHOLD / 10) - gc_cons_threshold = GC_DEFAULT_THRESHOLD / 10; - - gc_relative_threshold = 0; - if (FLOATP (Vgc_cons_percentage)) - { /* Set gc_cons_combined_threshold. */ - double tot = total_bytes_of_live_objects (); - - tot *= XFLOAT_DATA (Vgc_cons_percentage); - if (0 < tot) + if (!NILP (Vmemory_full)) + consing_until_gc = memory_full_cons_threshold; + else + { + intptr_t threshold = min (max (GC_DEFAULT_THRESHOLD, + gc_cons_threshold >> 3), + OBJECT_CT_MAX); + if (FLOATP (Vgc_cons_percentage)) { - if (tot < UINTPTR_MAX) - gc_relative_threshold = tot; - else - gc_relative_threshold = UINTPTR_MAX; + double tot = (XFLOAT_DATA (Vgc_cons_percentage) + * total_bytes_of_live_objects ()); + if (threshold < tot) + { + if (tot < OBJECT_CT_MAX) + threshold = tot; + else + threshold = OBJECT_CT_MAX; + } } + consing_until_gc = threshold; } if (garbage_collection_messages && NILP (Vmemory_full)) diff --git a/src/lisp.h b/src/lisp.h index 8f60963eb7..50a61cadd7 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3763,10 +3763,9 @@ #define CONS_TO_INTEGER(cons, type, var) \ extern void garbage_collect (void); extern const char *pending_malloc_warning; extern Lisp_Object zero_vector; -typedef uintptr_t byte_ct; /* System byte counts reported by GC. */ -extern byte_ct consing_since_gc; -extern byte_ct gc_relative_threshold; -extern byte_ct const memory_full_cons_threshold; +typedef intptr_t object_ct; /* Signed type of object counts reported by GC. */ +#define OBJECT_CT_MAX INTPTR_MAX +extern object_ct consing_until_gc; #ifdef HAVE_PDUMPER extern int number_finalizers_run; #endif @@ -4993,10 +4992,7 @@ #define FOR_EACH_ALIST_VALUE(head_var, list_var, value_var) \ INLINE void maybe_gc (void) { - if ((consing_since_gc > gc_cons_threshold - && consing_since_gc > gc_relative_threshold) - || (!NILP (Vmemory_full) - && consing_since_gc > memory_full_cons_threshold)) + if (consing_until_gc < 0) garbage_collect (); } -- 2.17.1