aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2019-09-03 13:03:34 -0700
committerPaul Eggert2019-09-03 13:03:47 -0700
commit97ffa339b6d67cebcbefbdfaa2880214adab639c (patch)
treedcc425367088b475426c1b385f99de83c96ee70b
parentc34dbd80e72204cd0ac65254ff3145dbd916f5c5 (diff)
downloademacs-97ffa339b6d67cebcbefbdfaa2880214adab639c.tar.gz
emacs-97ffa339b6d67cebcbefbdfaa2880214adab639c.zip
Sync consing_until_gc with gc-cons-threshold
Add watchers for gc-cons-threshold and gc-cons-percentage that update consing_until_gc accordingly. Suggested by Eli Zaretskii (Bug#37006#52). * src/alloc.c (consing_threshold, bump_consing_until_gc) (watch_gc_cons_threshold, watch_gc_cons_percentage): New functions. (garbage_collect_1): Use consing_threshold. (syms_of_alloc): Arrange to watch gc-cons-threshold and gc-cons-percentage.
-rw-r--r--src/alloc.c100
1 files changed, 81 insertions, 19 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 39964c4b293..5f8ef0a5dda 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -5781,6 +5781,68 @@ mark_and_sweep_weak_table_contents (void)
5781 } 5781 }
5782} 5782}
5783 5783
5784/* Return the number of bytes to cons between GCs, assuming
5785 gc-cons-threshold is THRESHOLD and gc-cons-percentage is
5786 GC_CONS_PERCENTAGE. */
5787static intmax_t
5788consing_threshold (intmax_t threshold, Lisp_Object gc_cons_percentage)
5789{
5790 if (!NILP (Vmemory_full))
5791 return memory_full_cons_threshold;
5792 else
5793 {
5794 threshold = max (threshold, GC_DEFAULT_THRESHOLD / 10);
5795 if (FLOATP (gc_cons_percentage))
5796 {
5797 double tot = (XFLOAT_DATA (gc_cons_percentage)
5798 * total_bytes_of_live_objects ());
5799 if (threshold < tot)
5800 {
5801 if (tot < INTMAX_MAX)
5802 threshold = tot;
5803 else
5804 threshold = INTMAX_MAX;
5805 }
5806 }
5807 return threshold;
5808 }
5809}
5810
5811/* Increment consing_until_gc by DIFF, avoiding overflow. */
5812static Lisp_Object
5813bump_consing_until_gc (intmax_t diff)
5814{
5815 /* If consing_until_gc is negative leave it alone, since this prevents
5816 negative integer overflow and a GC would have been done soon anyway. */
5817 if (0 <= consing_until_gc
5818 && INT_ADD_WRAPV (consing_until_gc, diff, &consing_until_gc))
5819 consing_until_gc = INTMAX_MAX;
5820 return Qnil;
5821}
5822
5823/* Watch changes to gc-cons-threshold. */
5824static Lisp_Object
5825watch_gc_cons_threshold (Lisp_Object symbol, Lisp_Object newval,
5826 Lisp_Object operation, Lisp_Object where)
5827{
5828 intmax_t new_threshold;
5829 int diff = (INTEGERP (newval) && integer_to_intmax (newval, &new_threshold)
5830 ? (consing_threshold (new_threshold, Vgc_cons_percentage)
5831 - consing_threshold (gc_cons_threshold, Vgc_cons_percentage))
5832 : 0);
5833 return bump_consing_until_gc (diff);
5834}
5835
5836/* Watch changes to gc-cons-percentage. */
5837static Lisp_Object
5838watch_gc_cons_percentage (Lisp_Object symbol, Lisp_Object newval,
5839 Lisp_Object operation, Lisp_Object where)
5840{
5841 int diff = (consing_threshold (consing_until_gc, newval)
5842 - consing_threshold (consing_until_gc, Vgc_cons_percentage));
5843 return bump_consing_until_gc (diff);
5844}
5845
5784/* Subroutine of Fgarbage_collect that does most of the work. */ 5846/* Subroutine of Fgarbage_collect that does most of the work. */
5785static bool 5847static bool
5786garbage_collect_1 (struct gcstat *gcst) 5848garbage_collect_1 (struct gcstat *gcst)
@@ -5923,25 +5985,8 @@ garbage_collect_1 (struct gcstat *gcst)
5923 5985
5924 unblock_input (); 5986 unblock_input ();
5925 5987
5926 if (!NILP (Vmemory_full)) 5988 consing_until_gc = consing_threshold (gc_cons_threshold,
5927 consing_until_gc = memory_full_cons_threshold; 5989 Vgc_cons_percentage);
5928 else
5929 {
5930 intmax_t threshold = max (gc_cons_threshold, GC_DEFAULT_THRESHOLD / 10);
5931 if (FLOATP (Vgc_cons_percentage))
5932 {
5933 double tot = (XFLOAT_DATA (Vgc_cons_percentage)
5934 * total_bytes_of_live_objects ());
5935 if (threshold < tot)
5936 {
5937 if (tot < INTMAX_MAX)
5938 threshold = tot;
5939 else
5940 threshold = INTMAX_MAX;
5941 }
5942 }
5943 consing_until_gc = threshold;
5944 }
5945 5990
5946 if (garbage_collection_messages && NILP (Vmemory_full)) 5991 if (garbage_collection_messages && NILP (Vmemory_full))
5947 { 5992 {
@@ -7362,6 +7407,7 @@ do hash-consing of the objects allocated to pure space. */);
7362 DEFSYM (Qheap, "heap"); 7407 DEFSYM (Qheap, "heap");
7363 DEFSYM (QAutomatic_GC, "Automatic GC"); 7408 DEFSYM (QAutomatic_GC, "Automatic GC");
7364 7409
7410 DEFSYM (Qgc_cons_percentage, "gc-cons-percentage");
7365 DEFSYM (Qgc_cons_threshold, "gc-cons-threshold"); 7411 DEFSYM (Qgc_cons_threshold, "gc-cons-threshold");
7366 DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots"); 7412 DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots");
7367 7413
@@ -7395,6 +7441,22 @@ N should be nonnegative. */);
7395 defsubr (&Smemory_info); 7441 defsubr (&Smemory_info);
7396 defsubr (&Smemory_use_counts); 7442 defsubr (&Smemory_use_counts);
7397 defsubr (&Ssuspicious_object); 7443 defsubr (&Ssuspicious_object);
7444
7445 Lisp_Object watcher;
7446
7447 static union Aligned_Lisp_Subr Swatch_gc_cons_threshold =
7448 {{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) },
7449 { .a4 = watch_gc_cons_threshold },
7450 4, 4, "watch_gc_cons_threshold", 0, 0}};
7451 XSETSUBR (watcher, &Swatch_gc_cons_threshold.s);
7452 Fadd_variable_watcher (Qgc_cons_threshold, watcher);
7453
7454 static union Aligned_Lisp_Subr Swatch_gc_cons_percentage =
7455 {{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) },
7456 { .a4 = watch_gc_cons_percentage },
7457 4, 4, "watch_gc_cons_percentage", 0, 0}};
7458 XSETSUBR (watcher, &Swatch_gc_cons_percentage.s);
7459 Fadd_variable_watcher (Qgc_cons_percentage, watcher);
7398} 7460}
7399 7461
7400#ifdef HAVE_X_WINDOWS 7462#ifdef HAVE_X_WINDOWS