emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 7e29eae: Suppress GC stats when obviously not neede


From: Paul Eggert
Subject: [Emacs-diffs] master 7e29eae: Suppress GC stats when obviously not needed
Date: Fri, 1 Mar 2019 12:09:52 -0500 (EST)

branch: master
commit 7e29eae023c8158d41eba02c2367e70cbee53642
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    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.
---
 lib-src/make-docfile.c |   3 +
 src/alloc.c            | 237 +++++++++++++++++++++++--------------------------
 src/lisp.h             |   3 +-
 src/pdumper.c          |   2 +-
 4 files changed, 119 insertions(+), 126 deletions(-)

diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c
index 05a0847..ccd245e 100644
--- a/lib-src/make-docfile.c
+++ b/lib-src/make-docfile.c
@@ -1107,6 +1107,9 @@ scan_c_stream (FILE *infile)
                g->flags |= DEFUN_noreturn;
              if (strstr (input_buffer, "const"))
                g->flags |= DEFUN_const;
+
+             /* Although the noinline attribute is no longer used,
+                leave its support in, in case it's needed later.  */
              if (strstr (input_buffer, "noinline"))
                g->flags |= DEFUN_noinline;
            }
diff --git a/src/alloc.c b/src/alloc.c
index a0d0a61..7d63e3c 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -253,9 +253,17 @@ typedef intptr_t object_ct;
 
 /* Number of live and free conses etc.  */
 
-static object_ct total_conses, total_symbols, total_buffers;
-static object_ct total_free_conses, total_free_symbols;
-static object_ct total_free_floats, total_floats;
+struct gcstat
+{
+  object_ct total_conses, total_free_conses;
+  object_ct total_symbols, total_free_symbols;
+  object_ct total_strings, total_free_strings;
+  byte_ct total_string_bytes;
+  object_ct total_vectors, total_vector_slots, total_free_vector_slots;
+  object_ct total_floats, total_free_floats;
+  object_ct total_intervals, total_free_intervals;
+  object_ct total_buffers;
+} gcstat;
 
 /* Points to memory space allocated as "spare", to be freed if we run
    out of memory.  We keep one large block, four cons-blocks, and
@@ -1538,10 +1546,6 @@ static struct interval_block *interval_block;
 
 static int interval_block_index = INTERVAL_BLOCK_SIZE;
 
-/* Number of free and live intervals.  */
-
-static object_ct total_free_intervals, total_intervals;
-
 /* List of free intervals.  */
 
 static INTERVAL interval_free_list;
@@ -1570,7 +1574,7 @@ make_interval (void)
          newi->next = interval_block;
          interval_block = newi;
          interval_block_index = 0;
-         total_free_intervals += INTERVAL_BLOCK_SIZE;
+         gcstat.total_free_intervals += INTERVAL_BLOCK_SIZE;
        }
       val = &interval_block->intervals[interval_block_index++];
     }
@@ -1579,7 +1583,7 @@ make_interval (void)
 
   consing_since_gc += sizeof (struct interval);
   intervals_consed++;
-  total_free_intervals--;
+  gcstat.total_free_intervals--;
   RESET_INTERVAL (val);
   val->gcmarkbit = 0;
   return val;
@@ -1755,14 +1759,6 @@ static struct string_block *string_blocks;
 
 static struct Lisp_String *string_free_list;
 
-/* Number of live and free Lisp_Strings.  */
-
-static object_ct total_strings, total_free_strings;
-
-/* Number of bytes used by live strings.  */
-
-static byte_ct total_string_bytes;
-
 /* Given a pointer to a Lisp_String S which is on the free-list
    string_free_list, return a pointer to its successor in the
    free-list.  */
@@ -1972,7 +1968,7 @@ allocate_string (void)
          string_free_list = ptr_bounds_clip (s, sizeof *s);
        }
 
-      total_free_strings += STRING_BLOCK_SIZE;
+      gcstat.total_free_strings += STRING_BLOCK_SIZE;
     }
 
   check_string_free_list ();
@@ -1983,8 +1979,8 @@ allocate_string (void)
 
   MALLOC_UNBLOCK_INPUT;
 
-  --total_free_strings;
-  ++total_strings;
+  gcstat.total_free_strings--;
+  gcstat.total_strings++;
   ++strings_consed;
   consing_since_gc += sizeof *s;
 
@@ -2119,8 +2115,8 @@ sweep_strings (void)
   struct string_block *live_blocks = NULL;
 
   string_free_list = NULL;
-  total_strings = total_free_strings = 0;
-  total_string_bytes = 0;
+  gcstat.total_strings = gcstat.total_free_strings = 0;
+  gcstat.total_string_bytes = 0;
 
   /* Scan strings_blocks, free Lisp_Strings that aren't marked.  */
   for (b = string_blocks; b; b = next)
@@ -2145,8 +2141,8 @@ sweep_strings (void)
                  /* Do not use string_(set|get)_intervals here.  */
                  s->u.s.intervals = balance_intervals (s->u.s.intervals);
 
-                 ++total_strings;
-                 total_string_bytes += STRING_BYTES (s);
+                 gcstat.total_strings++;
+                 gcstat.total_string_bytes += STRING_BYTES (s);
                }
              else
                {
@@ -2186,14 +2182,14 @@ sweep_strings (void)
       /* Free blocks that contain free Lisp_Strings only, except
         the first two of them.  */
       if (nfree == STRING_BLOCK_SIZE
-         && total_free_strings > STRING_BLOCK_SIZE)
+         && gcstat.total_free_strings > STRING_BLOCK_SIZE)
        {
          lisp_free (b);
          string_free_list = free_list_before;
        }
       else
        {
-         total_free_strings += nfree;
+         gcstat.total_free_strings += nfree;
          b->next = live_blocks;
          live_blocks = b;
        }
@@ -2701,7 +2697,7 @@ make_float (double float_value)
          memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
          float_block = new;
          float_block_index = 0;
-         total_free_floats += FLOAT_BLOCK_SIZE;
+         gcstat.total_free_floats += FLOAT_BLOCK_SIZE;
        }
       XSETFLOAT (val, &float_block->floats[float_block_index]);
       float_block_index++;
@@ -2713,7 +2709,7 @@ make_float (double float_value)
   eassert (!XFLOAT_MARKED_P (XFLOAT (val)));
   consing_since_gc += sizeof (struct Lisp_Float);
   floats_consed++;
-  total_free_floats--;
+  gcstat.total_free_floats--;
   return val;
 }
 
@@ -2779,7 +2775,7 @@ free_cons (struct Lisp_Cons *ptr)
   ptr->u.s.car = Vdead;
   cons_free_list = ptr;
   consing_since_gc -= sizeof *ptr;
-  total_free_conses++;
+  gcstat.total_free_conses++;
 }
 
 DEFUN ("cons", Fcons, Scons, 2, 2, 0,
@@ -2809,7 +2805,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
             distinct conses might not fit.  */
          if (max_conses < INTPTR_MAX / sizeof (struct Lisp_Cons)
              && (max_conses - CONS_BLOCK_SIZE
-                 < total_free_conses + total_conses))
+                 < gcstat.total_free_conses + gcstat.total_conses))
            memory_full (sizeof (struct cons_block));
 
          struct cons_block *new
@@ -2818,7 +2814,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
          new->next = cons_block;
          cons_block = new;
          cons_block_index = 0;
-         total_free_conses += CONS_BLOCK_SIZE;
+         gcstat.total_free_conses += CONS_BLOCK_SIZE;
        }
       XSETCONS (val, &cons_block->conses[cons_block_index]);
       cons_block_index++;
@@ -2830,7 +2826,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
   XSETCDR (val, cdr);
   eassert (!XCONS_MARKED_P (XCONS (val)));
   consing_since_gc += sizeof (struct Lisp_Cons);
-  total_free_conses--;
+  gcstat.total_free_conses--;
   cons_cells_consed++;
   return val;
 }
@@ -3080,14 +3076,6 @@ static struct large_vector *large_vectors;
 
 Lisp_Object zero_vector;
 
-/* Number of live vectors.  */
-
-static object_ct total_vectors;
-
-/* Total size of live and free vectors, in Lisp_Object units.  */
-
-static object_ct total_vector_slots, total_free_vector_slots;
-
 /* Common shortcut to setup vector on a free list.  */
 
 static void
@@ -3102,7 +3090,7 @@ setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t 
nbytes)
   eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX);
   set_next_vector (v, vector_free_lists[vindex]);
   vector_free_lists[vindex] = v;
-  total_free_vector_slots += nbytes / word_size;
+  gcstat.total_free_vector_slots += nbytes / word_size;
 }
 
 /* Get a new vector block.  */
@@ -3150,7 +3138,7 @@ allocate_vector_from_block (ptrdiff_t nbytes)
     {
       vector = vector_free_lists[index];
       vector_free_lists[index] = next_vector (vector);
-      total_free_vector_slots -= nbytes / word_size;
+      gcstat.total_free_vector_slots -= nbytes / word_size;
       return vector;
     }
 
@@ -3164,7 +3152,7 @@ allocate_vector_from_block (ptrdiff_t nbytes)
        /* This vector is larger than requested.  */
        vector = vector_free_lists[index];
        vector_free_lists[index] = next_vector (vector);
-       total_free_vector_slots -= nbytes / word_size;
+       gcstat.total_free_vector_slots -= nbytes / word_size;
 
        /* Excess bytes are used for the smaller vector,
           which should be set on an appropriate free list.  */
@@ -3295,7 +3283,8 @@ sweep_vectors (void)
   struct large_vector *lv, **lvprev = &large_vectors;
   struct Lisp_Vector *vector, *next;
 
-  total_vectors = total_vector_slots = total_free_vector_slots = 0;
+  gcstat.total_vectors = 0;
+  gcstat.total_vector_slots = gcstat.total_free_vector_slots = 0;
   memset (vector_free_lists, 0, sizeof (vector_free_lists));
 
   /* Looking through vector blocks.  */
@@ -3310,9 +3299,9 @@ sweep_vectors (void)
          if (XVECTOR_MARKED_P (vector))
            {
              XUNMARK_VECTOR (vector);
-             total_vectors++;
+             gcstat.total_vectors++;
              ptrdiff_t nbytes = vector_nbytes (vector);
-             total_vector_slots += nbytes / word_size;
+             gcstat.total_vector_slots += nbytes / word_size;
              next = ADVANCE (vector, nbytes);
            }
          else
@@ -3364,12 +3353,11 @@ sweep_vectors (void)
       if (XVECTOR_MARKED_P (vector))
        {
          XUNMARK_VECTOR (vector);
-         total_vectors++;
-         if (vector->header.size & PSEUDOVECTOR_FLAG)
-            total_vector_slots += vector_nbytes (vector) / word_size;
-         else
-           total_vector_slots
-             += header_size / word_size + vector->header.size;
+         gcstat.total_vectors++;
+         gcstat.total_vector_slots
+           += (vector->header.size & PSEUDOVECTOR_FLAG
+               ? vector_nbytes (vector) / word_size
+               : header_size / word_size + vector->header.size);
          lvprev = &lv->next;
        }
       else
@@ -3703,7 +3691,7 @@ Its value is void, and its function definition and 
property list are nil.  */)
          new->next = symbol_block;
          symbol_block = new;
          symbol_block_index = 0;
-         total_free_symbols += SYMBOL_BLOCK_SIZE;
+         gcstat.total_free_symbols += SYMBOL_BLOCK_SIZE;
        }
       XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]);
       symbol_block_index++;
@@ -3714,7 +3702,7 @@ Its value is void, and its function definition and 
property list are nil.  */)
   init_symbol (val, name);
   consing_since_gc += sizeof (struct Lisp_Symbol);
   symbols_consed++;
-  total_free_symbols--;
+  gcstat.total_free_symbols--;
   return val;
 }
 
@@ -4976,7 +4964,7 @@ mark_memory (void *start, void *end)
      {
        Lisp_Object obj = build_string ("test");
        struct Lisp_String *s = XSTRING (obj);
-       Fgarbage_collect ();
+       garbage_collect ();
        fprintf (stderr, "test '%s'\n", s->u.s.data);
        return Qnil;
      }
@@ -5774,13 +5762,13 @@ static byte_ct
 total_bytes_of_live_objects (void)
 {
   byte_ct tot = 0;
-  tot += object_bytes (total_conses, sizeof (struct Lisp_Cons));
-  tot += object_bytes (total_symbols, sizeof (struct Lisp_Symbol));
-  tot += total_string_bytes;
-  tot += object_bytes (total_vector_slots, word_size);
-  tot += object_bytes (total_floats, sizeof (struct Lisp_Float));
-  tot += object_bytes (total_intervals, sizeof (struct interval));
-  tot += object_bytes (total_strings, sizeof (struct Lisp_String));
+  tot += object_bytes (gcstat.total_conses, sizeof (struct Lisp_Cons));
+  tot += object_bytes (gcstat.total_symbols, sizeof (struct Lisp_Symbol));
+  tot += gcstat.total_string_bytes;
+  tot += object_bytes (gcstat.total_vector_slots, word_size);
+  tot += object_bytes (gcstat.total_floats, sizeof (struct Lisp_Float));
+  tot += object_bytes (gcstat.total_intervals, sizeof (struct interval));
+  tot += object_bytes (gcstat.total_strings, sizeof (struct Lisp_String));
   return tot;
 }
 
@@ -6029,22 +6017,15 @@ mark_and_sweep_weak_table_contents (void)
     }
 }
 
-/* Subroutine of Fgarbage_collect that does most of the work.  It is a
-   separate function so that we could limit mark_stack in searching
-   the stack frames below this function, thus avoiding the rare cases
-   where mark_stack finds values that look like live Lisp objects on
-   portions of stack that couldn't possibly contain such live objects.
-   For more details of this, see the discussion at
-   https://lists.gnu.org/r/emacs-devel/2014-05/msg00270.html.  */
-static Lisp_Object
-garbage_collect_1 (void *end)
+/* Subroutine of Fgarbage_collect that does most of the work.  */
+static bool
+garbage_collect_1 (struct gcstat *gcst)
 {
   struct buffer *nextb;
   char stack_top_variable;
   bool message_p;
   ptrdiff_t count = SPECPDL_INDEX ();
   struct timespec start;
-  Lisp_Object retval = Qnil;
   byte_ct tot_before = 0;
 
   eassert (weak_hash_tables == NULL);
@@ -6052,7 +6033,7 @@ garbage_collect_1 (void *end)
   /* Can't GC if pure storage overflowed because we can't determine
      if something is a pure object or not.  */
   if (pure_bytes_used_before_overflow)
-    return Qnil;
+    return false;
 
   /* Record this function, so it appears on the profiler's backtraces.  */
   record_in_backtrace (QAutomatic_GC, 0, 0);
@@ -6215,40 +6196,7 @@ garbage_collect_1 (void *end)
 
   unbind_to (count, Qnil);
 
-  Lisp_Object total[] = {
-    list4 (Qconses, make_fixnum (sizeof (struct Lisp_Cons)),
-          make_int (total_conses),
-          make_int (total_free_conses)),
-    list4 (Qsymbols, make_fixnum (sizeof (struct Lisp_Symbol)),
-          make_int (total_symbols),
-          make_int (total_free_symbols)),
-    list4 (Qstrings, make_fixnum (sizeof (struct Lisp_String)),
-          make_int (total_strings),
-          make_int (total_free_strings)),
-    list3 (Qstring_bytes, make_fixnum (1),
-          make_int (total_string_bytes)),
-    list3 (Qvectors,
-          make_fixnum (header_size + sizeof (Lisp_Object)),
-          make_int (total_vectors)),
-    list4 (Qvector_slots, make_fixnum (word_size),
-          make_int (total_vector_slots),
-          make_int (total_free_vector_slots)),
-    list4 (Qfloats, make_fixnum (sizeof (struct Lisp_Float)),
-          make_int (total_floats),
-          make_int (total_free_floats)),
-    list4 (Qintervals, make_fixnum (sizeof (struct interval)),
-          make_int (total_intervals),
-          make_int (total_free_intervals)),
-    list3 (Qbuffers, make_fixnum (sizeof (struct buffer)),
-          make_int (total_buffers)),
-
-#ifdef DOUG_LEA_MALLOC
-    list4 (Qheap, make_fixnum (1024),
-          make_int ((mallinfo ().uordblks + 1023) >> 10),
-          make_int ((mallinfo ().fordblks + 1023) >> 10)),
-#endif
-  };
-  retval = CALLMANY (Flist, total);
+  *gcst = gcstat;
 
   /* GC is complete: now we can run our finalizer callbacks.  */
   run_finalizers (&doomed_finalizers);
@@ -6278,7 +6226,14 @@ garbage_collect_1 (void *end)
       malloc_probe (min (swept, SIZE_MAX));
     }
 
-  return retval;
+  return true;
+}
+
+void
+garbage_collect (void)
+{
+  struct gcstat gcst;
+  garbage_collect_1 (&gcst);
 }
 
 DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "",
@@ -6295,13 +6250,47 @@ where each entry has the form (NAME SIZE USED FREE), 
where:
   to return them to the OS).
 However, if there was overflow in pure space, `garbage-collect'
 returns nil, because real GC can't be done.
-See Info node `(elisp)Garbage Collection'.  */
-       attributes: noinline)
+See Info node `(elisp)Garbage Collection'.  */)
   (void)
 {
-  void *end;
-  SET_STACK_TOP_ADDRESS (&end);
-  return garbage_collect_1 (end);
+  struct gcstat gcst;
+  if (!garbage_collect_1 (&gcst))
+    return Qnil;
+
+  Lisp_Object total[] = {
+    list4 (Qconses, make_fixnum (sizeof (struct Lisp_Cons)),
+          make_int (gcst.total_conses),
+          make_int (gcst.total_free_conses)),
+    list4 (Qsymbols, make_fixnum (sizeof (struct Lisp_Symbol)),
+          make_int (gcst.total_symbols),
+          make_int (gcst.total_free_symbols)),
+    list4 (Qstrings, make_fixnum (sizeof (struct Lisp_String)),
+          make_int (gcst.total_strings),
+          make_int (gcst.total_free_strings)),
+    list3 (Qstring_bytes, make_fixnum (1),
+          make_int (gcst.total_string_bytes)),
+    list3 (Qvectors,
+          make_fixnum (header_size + sizeof (Lisp_Object)),
+          make_int (gcst.total_vectors)),
+    list4 (Qvector_slots, make_fixnum (word_size),
+          make_int (gcst.total_vector_slots),
+          make_int (gcst.total_free_vector_slots)),
+    list4 (Qfloats, make_fixnum (sizeof (struct Lisp_Float)),
+          make_int (gcst.total_floats),
+          make_int (gcst.total_free_floats)),
+    list4 (Qintervals, make_fixnum (sizeof (struct interval)),
+          make_int (gcst.total_intervals),
+          make_int (gcst.total_free_intervals)),
+    list3 (Qbuffers, make_fixnum (sizeof (struct buffer)),
+          make_int (gcst.total_buffers)),
+
+#ifdef DOUG_LEA_MALLOC
+    list4 (Qheap, make_fixnum (1024),
+          make_int ((mallinfo ().uordblks + 1023) >> 10),
+          make_int ((mallinfo ().fordblks + 1023) >> 10)),
+#endif
+  };
+  return CALLMANY (Flist, total);
 }
 
 /* Mark Lisp objects in glyph matrix MATRIX.  Currently the
@@ -7003,8 +6992,8 @@ sweep_conses (void)
           cprev = &cblk->next;
         }
     }
-  total_conses = num_used;
-  total_free_conses = num_free;
+  gcstat.total_conses = num_used;
+  gcstat.total_free_conses = num_free;
 }
 
 NO_INLINE /* For better stack traces */
@@ -7052,8 +7041,8 @@ sweep_floats (void)
           fprev = &fblk->next;
         }
     }
-  total_floats = num_used;
-  total_free_floats = num_free;
+  gcstat.total_floats = num_used;
+  gcstat.total_free_floats = num_free;
 }
 
 NO_INLINE /* For better stack traces */
@@ -7101,8 +7090,8 @@ sweep_intervals (void)
           iprev = &iblk->next;
         }
     }
-  total_intervals = num_used;
-  total_free_intervals = num_free;
+  gcstat.total_intervals = num_used;
+  gcstat.total_free_intervals = num_free;
 }
 
 NO_INLINE /* For better stack traces */
@@ -7170,8 +7159,8 @@ sweep_symbols (void)
           sprev = &sblk->next;
         }
     }
-  total_symbols = num_used;
-  total_free_symbols = num_free;
+  gcstat.total_symbols = num_used;
+  gcstat.total_free_symbols = num_free;
 }
 
 /* Remove BUFFER's markers that are due to be swept.  This is needed since
@@ -7195,9 +7184,9 @@ NO_INLINE /* For better stack traces */
 static void
 sweep_buffers (void)
 {
-  register struct buffer *buffer, **bprev = &all_buffers;
+  struct buffer *buffer, **bprev = &all_buffers;
 
-  total_buffers = 0;
+  gcstat.total_buffers = 0;
   for (buffer = all_buffers; buffer; buffer = *bprev)
     if (!vectorlike_marked_p (&buffer->header))
       {
@@ -7211,7 +7200,7 @@ sweep_buffers (void)
         /* Do not use buffer_(set|get)_intervals here.  */
         buffer->text->intervals = balance_intervals (buffer->text->intervals);
         unchain_dead_markers (buffer);
-        total_buffers++;
+       gcstat.total_buffers++;
         bprev = &buffer->next;
       }
 }
diff --git a/src/lisp.h b/src/lisp.h
index 388cd04..3257693 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3763,6 +3763,7 @@ extern void alloc_unexec_post (void);
 extern void mark_maybe_objects (Lisp_Object *, ptrdiff_t);
 extern void mark_stack (char *, char *);
 extern void flush_stack_call_func (void (*func) (void *arg), void *arg);
+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.  */
@@ -5003,7 +5004,7 @@ maybe_gc (void)
        && consing_since_gc > gc_relative_threshold)
       || (!NILP (Vmemory_full)
          && consing_since_gc > memory_full_cons_threshold))
-    Fgarbage_collect ();
+    garbage_collect ();
 }
 
 INLINE_HEADER_END
diff --git a/src/pdumper.c b/src/pdumper.c
index 724ea7b..4d35fd1 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -4055,7 +4055,7 @@ types.  */)
   /* Clear out any detritus in memory.  */
   do {
     number_finalizers_run = 0;
-    Fgarbage_collect ();
+    garbage_collect ();
   } while (number_finalizers_run);
 
   ptrdiff_t count = SPECPDL_INDEX ();



reply via email to

[Prev in Thread] Current Thread [Next in Thread]