summaryrefslogtreecommitdiff
path: root/gcc/ggc-common.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2004-03-03 11:25:51 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2004-03-03 11:25:51 +0000
commit674b05f5734c0ce4249a6128d640beec4689956e (patch)
tree2b3885b2b287da398b70600d8381767cc76aa181 /gcc/ggc-common.c
parent0eaca434ca26e585c3d61781f006859981850551 (diff)
downloadgcc-674b05f5734c0ce4249a6128d640beec4689956e.tar.gz
* ggc-common.c (ggc_alloc_cleared_stat, ggc_realloc_stat):
Rename from ...; make statistics transparent. (ggc_alloc_cleared, ggc_realloc_stat): ... these. (loc_descriptor): New structure. (hash_descriptor, eq_descriptor, loc_descriptor, cmp_statistics, add_statistics): New static function. (ggc_record_overhead, dump_statistics): New global function. * ggc-none.c (ggc_alloc_types_stat, ggc_alloc_stat, ggc_alloc_zone_stat, ggc_alloc_cleared_stat, ggc_realloc_stat, ggc_alloc_typed_stat): Rename from ...; accept locations (ggc_alloc_types, ggc_alloc, ggc_alloc_zone, ggc_alloc_cleared, ggc_realloc, ggc_alloc_typed): ... this one. from ...; accept locations * ggc-page.c (ggc_alloc_typed_stat, ggc_alloc_zone_stat, ggc_alloc_stat): Rename from ... ; pass locations * ggc-page.c (ggc_alloc_typed, ggc_alloc_zone, ggc_alloc): ... this one. (ggc_alloc_stat): Record overehead. * ggc.h (ggc_alloc_types, ggc_alloc, ggc_alloc_zone, ggc_alloc_cleared, ggc_realloc, ggc_alloc_typed): Turn to macros (ggc_alloc_types_stat, ggc_alloc_stat, ggc_alloc_zone_stat, ggc_alloc_cleared_stat, ggc_realloc_stat, ggc_alloc_typed_stat): Declare. (dump_ggc_loc_satistics, ggc_record_overehead): Declare. * langhooks.h (lhd_make_node): Declare. (LANG_HOOKS_MAKE_TYPE): Default to new function, * langhooks.c (lhd_make_node): New. * rtl.c (rtx_alloc_stat, swallow_copy_rtx_stat): Rename from ... ; pass locations. (rtx_alloc, swallow_copy_rtx): ... this one. * rtl.h (rtx_alloc, swallow_copy_rtx): Turn to macros. * rtl.c (rtx_alloc_stat, swallow_copy_rtx_stat): Declare. * toplpev.c (finalize): Dump stats. * tree.c (make_node_stat, copy_node_stat, make_tree_vec_stat, build_tree_list_stat, tree_cons_stat, build?_stat, build_decl_stat): Rename from ... ; pass locators. (make_node, copy_node, make_tree_vec, build_tree_list, tree_cons, build?, build_decl): Declare. * tree.h (make_node_stat, copy_node_stat, make_tree_vec_stat, build_tree_list_stat, tree_cons_stat, build?_stat, build_decl_stat): Declare. (make_node, copy_node, make_tree_vec, build_tree_list, tree_cons, build?, build_decl): New macros. * Makefile.in (RTL_H, TREE_H): Add statistics.h dependency. * statistics.h: New file. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@78826 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ggc-common.c')
-rw-r--r--gcc/ggc-common.c147
1 files changed, 142 insertions, 5 deletions
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index 3d096b9e133..70a0d084c81 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -129,22 +129,22 @@ ggc_mark_roots (void)
/* Allocate a block of memory, then clear it. */
void *
-ggc_alloc_cleared (size_t size)
+ggc_alloc_cleared_stat (size_t size MEM_STAT_DECL)
{
- void *buf = ggc_alloc (size);
+ void *buf = ggc_alloc_stat (size PASS_MEM_STAT);
memset (buf, 0, size);
return buf;
}
/* Resize a block of memory, possibly re-allocating it. */
void *
-ggc_realloc (void *x, size_t size)
+ggc_realloc_stat (void *x, size_t size MEM_STAT_DECL)
{
void *r;
size_t old_size;
if (x == NULL)
- return ggc_alloc (size);
+ return ggc_alloc_stat (size PASS_MEM_STAT);
old_size = ggc_get_size (x);
@@ -166,7 +166,7 @@ ggc_realloc (void *x, size_t size)
return x;
}
- r = ggc_alloc (size);
+ r = ggc_alloc_stat (size PASS_MEM_STAT);
/* Since ggc_get_size returns the size of the pool, not the size of the
individually allocated object, we'd access parts of the old object
@@ -761,3 +761,140 @@ init_ggc_heuristics (void)
set_param_value ("ggc-min-heapsize", ggc_min_heapsize_heuristic());
#endif
}
+
+#ifdef GATHER_STATISTICS
+
+/* Datastructure used to store per-call-site statistics. */
+struct loc_descriptor
+{
+ const char *file;
+ int line;
+ const char *function;
+ int times;
+ size_t allocated;
+ size_t overhead;
+};
+
+/* Hashtable used for statistics. */
+static htab_t loc_hash;
+
+/* Hash table helpers functions. */
+static hashval_t
+hash_descriptor (const void *p)
+{
+ const struct loc_descriptor *d = p;
+
+ return htab_hash_pointer (d->function) | d->line;
+}
+
+static int
+eq_descriptor (const void *p1, const void *p2)
+{
+ const struct loc_descriptor *d = p1;
+ const struct loc_descriptor *d2 = p2;
+
+ return (d->file == d2->file && d->line == d2->line
+ && d->function == d2->function);
+}
+
+/* Return descriptor for given call site, create new one if needed. */
+static struct loc_descriptor *
+loc_descriptor (const char *name, int line, const char *function)
+{
+ struct loc_descriptor loc;
+ struct loc_descriptor **slot;
+
+ loc.file = name;
+ loc.line = line;
+ loc.function = function;
+ if (!loc_hash)
+ loc_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
+
+ slot = (struct loc_descriptor **) htab_find_slot (loc_hash, &loc, 1);
+ if (*slot)
+ return *slot;
+ *slot = xcalloc (sizeof (**slot), 1);
+ (*slot)->file = name;
+ (*slot)->line = line;
+ (*slot)->function = function;
+ return *slot;
+}
+
+/* Record ALLOCATED and OVERHEAD bytes to descritor NAME:LINE (FUNCTION). */
+void ggc_record_overhead (size_t allocated, size_t overhead,
+ const char *name, int line, const char *function)
+{
+ struct loc_descriptor *loc = loc_descriptor (name, line, function);
+
+ loc->times++;
+ loc->allocated+=allocated;
+ loc->overhead+=overhead;
+}
+
+/* Helper for qsort; sort descriptors by amount of memory consumed. */
+static int
+cmp_statistic (const void *loc1, const void *loc2)
+{
+ struct loc_descriptor *l1 = *(struct loc_descriptor **) loc1;
+ struct loc_descriptor *l2 = *(struct loc_descriptor **) loc2;
+ return (l1->allocated + l1->overhead) - (l2->allocated + l2->overhead);
+}
+
+/* Collect array of the descriptors from hashtable. */
+struct loc_descriptor **loc_array;
+static int
+add_statistics (void **slot, void *b)
+{
+ int *n = (int *)b;
+ loc_array[*n] = (struct loc_descriptor *) *slot;
+ (*n)++;
+ return 1;
+}
+
+/* Dump per-site memory statistics. */
+#endif
+void dump_ggc_loc_statistics (void)
+{
+#ifdef GATHER_STATISTICS
+ int nentries = 0;
+ char s[4096];
+ size_t count, size, overhead;
+ int i;
+
+ loc_array = xcalloc (sizeof (*loc_array), loc_hash->n_elements);
+ fprintf (stderr, "-------------------------------------------------------\n");
+ fprintf (stderr, "\n%-60s %10s %10s %10s\n",
+ "source location", "Times", "Allocated", "Overhead");
+ fprintf (stderr, "-------------------------------------------------------\n");
+ count = 0;
+ size = 0;
+ overhead = 0;
+ htab_traverse (loc_hash, add_statistics, &nentries);
+ qsort (loc_array, nentries, sizeof (*loc_array), cmp_statistic);
+ for (i = 0; i < nentries; i++)
+ {
+ struct loc_descriptor *d = loc_array[i];
+ size += d->allocated;
+ count += d->times;
+ overhead += d->overhead;
+ }
+ for (i = 0; i < nentries; i++)
+ {
+ struct loc_descriptor *d = loc_array[i];
+ if (d->allocated)
+ {
+ const char *s1 = d->file;
+ const char *s2;
+ while ((s2 = strstr (s1, "gcc/")))
+ s1 = s2 + 4;
+ sprintf (s, "%s:%i (%s)", s1, d->line, d->function);
+ fprintf (stderr, "%-60s %10i %10li %10li:%.3f%%\n", s,
+ d->times, (long)d->allocated, (long)d->overhead,
+ (d->allocated + d->overhead) *100.0 / (size + overhead));
+ }
+ }
+ fprintf (stderr, "%-60s %10ld %10ld %10ld\n",
+ "Total", (long)count, (long)size, (long)overhead);
+ fprintf (stderr, "-------------------------------------------------------\n");
+#endif
+}