Hello.
After my param to option transformation, we lost automatic GGC
detection. It's because init_ggc_heuristics is called before
init_options_struct which memsets all the values to zero first.
I've tested the patch with --enable-checking=release and I hope
Honza can test it more?
Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
Ready to be installed?
Thanks,
Martin
gcc/ChangeLog:
2019-11-18 Martin Liska <[email protected]>
* ggc-common.c (ggc_rlimit_bound): Move to opts.c
(ggc_min_expand_heuristic): Likewise.
(ggc_min_heapsize_heuristic): Likewise.
(init_ggc_heuristics): Likewise.
* ggc.h (init_ggc_heuristics): Remove declaration.
* opts.c (ggc_rlimit_bound): Moved here from ggc-common.c.
(ggc_min_expand_heuristic): Likewise.
(ggc_min_heapsize_heuristic): Likewise.
(init_ggc_heuristics): Likewise.
(init_options_struct): Init GGC params.
* toplev.c (general_init): Remove call to init_ggc_heuristics.
---
gcc/ggc-common.c | 103 ---------------------------------------------
gcc/ggc.h | 3 --
gcc/opts.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++
gcc/toplev.c | 4 --
4 files changed, 106 insertions(+), 110 deletions(-)
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index f6e393d7bb6..86aab015b91 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -715,109 +715,6 @@ mmap_gt_pch_use_address (void *base, size_t size, int fd, size_t offset)
}
#endif /* HAVE_MMAP_FILE */
-#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
-
-/* Modify the bound based on rlimits. */
-static double
-ggc_rlimit_bound (double limit)
-{
-#if defined(HAVE_GETRLIMIT)
- struct rlimit rlim;
-# if defined (RLIMIT_AS)
- /* RLIMIT_AS is what POSIX says is the limit on mmap. Presumably
- any OS which has RLIMIT_AS also has a working mmap that GCC will use. */
- if (getrlimit (RLIMIT_AS, &rlim) == 0
- && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
- && rlim.rlim_cur < limit)
- limit = rlim.rlim_cur;
-# elif defined (RLIMIT_DATA)
- /* ... but some older OSs bound mmap based on RLIMIT_DATA, or we
- might be on an OS that has a broken mmap. (Others don't bound
- mmap at all, apparently.) */
- if (getrlimit (RLIMIT_DATA, &rlim) == 0
- && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
- && rlim.rlim_cur < limit
- /* Darwin has this horribly bogus default setting of
- RLIMIT_DATA, to 6144Kb. No-one notices because RLIMIT_DATA
- appears to be ignored. Ignore such silliness. If a limit
- this small was actually effective for mmap, GCC wouldn't even
- start up. */
- && rlim.rlim_cur >= 8 * 1024 * 1024)
- limit = rlim.rlim_cur;
-# endif /* RLIMIT_AS or RLIMIT_DATA */
-#endif /* HAVE_GETRLIMIT */
-
- return limit;
-}
-
-/* Heuristic to set a default for GGC_MIN_EXPAND. */
-static int
-ggc_min_expand_heuristic (void)
-{
- double min_expand = physmem_total ();
-
- /* Adjust for rlimits. */
- min_expand = ggc_rlimit_bound (min_expand);
-
- /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding
- a lower bound of 30% and an upper bound of 100% (when RAM >= 1GB). */
- min_expand /= 1024*1024*1024;
- min_expand *= 70;
- min_expand = MIN (min_expand, 70);
- min_expand += 30;
-
- return min_expand;
-}
-
-/* Heuristic to set a default for GGC_MIN_HEAPSIZE. */
-static int
-ggc_min_heapsize_heuristic (void)
-{
- double phys_kbytes = physmem_total ();
- double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2);
-
- phys_kbytes /= 1024; /* Convert to Kbytes. */
- limit_kbytes /= 1024;
-
- /* The heuristic is RAM/8, with a lower bound of 4M and an upper
- bound of 128M (when RAM >= 1GB). */
- phys_kbytes /= 8;
-
-#if defined(HAVE_GETRLIMIT) && defined (RLIMIT_RSS)
- /* Try not to overrun the RSS limit while doing garbage collection.
- The RSS limit is only advisory, so no margin is subtracted. */
- {
- struct rlimit rlim;
- if (getrlimit (RLIMIT_RSS, &rlim) == 0
- && rlim.rlim_cur != (rlim_t) RLIM_INFINITY)
- phys_kbytes = MIN (phys_kbytes, rlim.rlim_cur / 1024);
- }
-# endif
-
- /* Don't blindly run over our data limit; do GC at least when the
- *next* GC would be within 20Mb of the limit or within a quarter of
- the limit, whichever is larger. If GCC does hit the data limit,
- compilation will fail, so this tries to be conservative. */
- limit_kbytes = MAX (0, limit_kbytes - MAX (limit_kbytes / 4, 20 * 1024));
- limit_kbytes = (limit_kbytes * 100) / (110 + ggc_min_expand_heuristic ());
- phys_kbytes = MIN (phys_kbytes, limit_kbytes);
-
- phys_kbytes = MAX (phys_kbytes, 4 * 1024);
- phys_kbytes = MIN (phys_kbytes, 128 * 1024);
-
- return phys_kbytes;
-}
-#endif
-
-void
-init_ggc_heuristics (void)
-{
-#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
- param_ggc_min_expand = ggc_min_expand_heuristic ();
- param_ggc_min_heapsize = ggc_min_heapsize_heuristic ();
-#endif
-}
-
/* GGC memory usage. */
class ggc_usage: public mem_usage
{
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 6c64caaafb2..04431439c5e 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -285,9 +285,6 @@ extern void ggc_print_statistics (void);
extern void stringpool_statistics (void);
-/* Heuristics. */
-extern void init_ggc_heuristics (void);
-
/* Report current heap memory use to stderr. */
extern void report_heap_memory_use (void);
diff --git a/gcc/opts.c b/gcc/opts.c
index addebf15365..7e363e5c1d6 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -275,6 +275,110 @@ init_opts_obstack (void)
gcc_obstack_init (&opts_obstack);
}
+#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
+
+/* Modify the bound based on rlimits. */
+
+static double
+ggc_rlimit_bound (double limit)
+{
+#if defined(HAVE_GETRLIMIT)
+ struct rlimit rlim;
+#if defined(RLIMIT_AS)
+ /* RLIMIT_AS is what POSIX says is the limit on mmap. Presumably
+ any OS which has RLIMIT_AS also has a working mmap that GCC will use. */
+ if (getrlimit (RLIMIT_AS, &rlim) == 0
+ && rlim.rlim_cur != (rlim_t) RLIM_INFINITY && rlim.rlim_cur < limit)
+ limit = rlim.rlim_cur;
+#elif defined(RLIMIT_DATA)
+ /* ... but some older OSs bound mmap based on RLIMIT_DATA, or we
+ might be on an OS that has a broken mmap. (Others don't bound
+ mmap at all, apparently.) */
+ if (getrlimit (RLIMIT_DATA, &rlim) == 0
+ && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
+ && rlim.rlim_cur < limit
+ /* Darwin has this horribly bogus default setting of
+ RLIMIT_DATA, to 6144Kb. No-one notices because RLIMIT_DATA
+ appears to be ignored. Ignore such silliness. If a limit
+ this small was actually effective for mmap, GCC wouldn't even
+ start up. */
+ && rlim.rlim_cur >= 8 * 1024 * 1024)
+ limit = rlim.rlim_cur;
+#endif /* RLIMIT_AS or RLIMIT_DATA */
+#endif /* HAVE_GETRLIMIT */
+
+ return limit;
+}
+
+/* Heuristic to set a default for GGC_MIN_EXPAND. */
+
+static int
+ggc_min_expand_heuristic (void)
+{
+ double min_expand = physmem_total ();
+
+ /* Adjust for rlimits. */
+ min_expand = ggc_rlimit_bound (min_expand);
+
+ /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding
+ a lower bound of 30% and an upper bound of 100% (when RAM >= 1GB). */
+ min_expand /= 1024 * 1024 * 1024;
+ min_expand *= 70;
+ min_expand = MIN (min_expand, 70);
+ min_expand += 30;
+
+ return min_expand;
+}
+
+/* Heuristic to set a default for GGC_MIN_HEAPSIZE. */
+static int
+ggc_min_heapsize_heuristic (void)
+{
+ double phys_kbytes = physmem_total ();
+ double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2);
+
+ phys_kbytes /= 1024; /* Convert to Kbytes. */
+ limit_kbytes /= 1024;
+
+ /* The heuristic is RAM/8, with a lower bound of 4M and an upper
+ bound of 128M (when RAM >= 1GB). */
+ phys_kbytes /= 8;
+
+#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_RSS)
+ /* Try not to overrun the RSS limit while doing garbage collection.
+ The RSS limit is only advisory, so no margin is subtracted. */
+ {
+ struct rlimit rlim;
+ if (getrlimit (RLIMIT_RSS, &rlim) == 0
+ && rlim.rlim_cur != (rlim_t) RLIM_INFINITY)
+ phys_kbytes = MIN (phys_kbytes, rlim.rlim_cur / 1024);
+ }
+#endif
+
+ /* Don't blindly run over our data limit; do GC at least when the
+ *next* GC would be within 20Mb of the limit or within a quarter of
+ the limit, whichever is larger. If GCC does hit the data limit,
+ compilation will fail, so this tries to be conservative. */
+ limit_kbytes = MAX (0, limit_kbytes - MAX (limit_kbytes / 4, 20 * 1024));
+ limit_kbytes = (limit_kbytes * 100) / (110 + ggc_min_expand_heuristic ());
+ phys_kbytes = MIN (phys_kbytes, limit_kbytes);
+
+ phys_kbytes = MAX (phys_kbytes, 4 * 1024);
+ phys_kbytes = MIN (phys_kbytes, 128 * 1024);
+
+ return phys_kbytes;
+}
+#endif
+
+static void
+init_ggc_heuristics (void)
+{
+#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
+ param_ggc_min_expand = ggc_min_expand_heuristic ();
+ param_ggc_min_heapsize = ggc_min_heapsize_heuristic ();
+#endif
+}
+
/* Initialize OPTS and OPTS_SET before using them in parsing options. */
void
@@ -289,6 +393,8 @@ init_options_struct (struct gcc_options *opts, struct gcc_options *opts_set)
if (opts_set)
memset (opts_set, 0, sizeof (*opts_set));
+ init_ggc_heuristics ();
+
/* Initialize whether `char' is signed. */
opts->x_flag_signed_char = DEFAULT_SIGNED_CHAR;
/* Set this to a special "uninitialized" value. The actual default
diff --git a/gcc/toplev.c b/gcc/toplev.c
index d4583bac66c..fa6d39355d0 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1240,10 +1240,6 @@ general_init (const char *argv0, bool init_signals)
/* Initialize register usage now so switches may override. */
init_reg_sets ();
- /* This must be done after global_init_params but before argument
- processing. */
- init_ggc_heuristics ();
-
/* Create the singleton holder for global state. This creates the
dump manager. */
g = new gcc::context ();