summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>1999-10-29 04:17:33 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>1999-10-29 04:17:33 +0000
commit4e00b6fd23bf82e4038e115609361fb0c62465f7 (patch)
tree8885ce2ea35f645ae60061b2f77bd345ad926d71 /gcc
parent637be39f421b23c745f14f52d76daf974cc93460 (diff)
downloadgcc-4e00b6fd23bf82e4038e115609361fb0c62465f7.tar.gz
* ggc.h (struct ggc_statistics): New type.
(ggc_get_size): New function. (ggc_print_statistics): Likewise. * ggc-common.c (ggc_stats): New variable. (ggc_mark_rtx_children): Keep statistics. (ggc_mark_tree_children): Likewise. (ggc_print_statistics): New function. * ggc-page.c (struct globals): Add bytes_mapped field. (alloc_anon): Update it. (release_pages): Likewise. (ggc_get_size): New function. (ggc_page_print_statistics): New function. * ggc-simple.c (ggc_get_size): New function. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@30251 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/ggc-common.c97
-rw-r--r--gcc/ggc-page.c65
-rw-r--r--gcc/ggc-simple.c9
-rw-r--r--gcc/ggc.h33
5 files changed, 217 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 97e54f562c0..aeb66bf3761 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,19 @@
+Thu Oct 28 21:16:35 1999 Mark Mitchell <mark@codesourcery.com>
+
+ * ggc.h (struct ggc_statistics): New type.
+ (ggc_get_size): New function.
+ (ggc_print_statistics): Likewise.
+ * ggc-common.c (ggc_stats): New variable.
+ (ggc_mark_rtx_children): Keep statistics.
+ (ggc_mark_tree_children): Likewise.
+ (ggc_print_statistics): New function.
+ * ggc-page.c (struct globals): Add bytes_mapped field.
+ (alloc_anon): Update it.
+ (release_pages): Likewise.
+ (ggc_get_size): New function.
+ (ggc_page_print_statistics): New function.
+ * ggc-simple.c (ggc_get_size): New function.
+
Fri Oct 29 06:32:44 1999 Geoffrey Keating <geoffk@cygnus.com>
* flow.c (propagate_block): When the last reference to a label
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index 2d8631dbd8b..fdc032294f8 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -30,6 +30,9 @@
#include "varray.h"
#include "ggc.h"
+/* Statistics about the allocation. */
+static ggc_statistics *ggc_stats;
+
static void ggc_mark_rtx_ptr PARAMS ((void *));
static void ggc_mark_tree_ptr PARAMS ((void *));
static void ggc_mark_tree_varray_ptr PARAMS ((void *));
@@ -211,10 +214,18 @@ ggc_mark_rtx_children (r)
{
const char *fmt;
int i;
+ enum rtx_code code = GET_CODE (r);
+
+ /* Collect statistics, if appropriate. */
+ if (ggc_stats)
+ {
+ ++ggc_stats->num_rtxs[(int) code];
+ ggc_stats->size_rtxs[(int) code] += ggc_get_size (r);
+ }
/* ??? If (some of) these are really pass-dependant info, do we have
any right poking our noses in? */
- switch (GET_CODE (r))
+ switch (code)
{
case JUMP_INSN:
ggc_mark_rtx (JUMP_LABEL (r));
@@ -289,12 +300,21 @@ void
ggc_mark_tree_children (t)
tree t;
{
+ enum tree_code code = TREE_CODE (t);
+
+ /* Collect statistics, if appropriate. */
+ if (ggc_stats)
+ {
+ ++ggc_stats->num_trees[(int) code];
+ ggc_stats->size_trees[(int) code] += ggc_get_size (t);
+ }
+
/* Bits from common. */
ggc_mark_tree (TREE_TYPE (t));
ggc_mark_tree (TREE_CHAIN (t));
/* Some nodes require special handling. */
- switch (TREE_CODE (t))
+ switch (code)
{
case TREE_LIST:
ggc_mark_tree (TREE_PURPOSE (t));
@@ -349,7 +369,7 @@ ggc_mark_tree_children (t)
}
/* But in general we can handle them by class. */
- switch (TREE_CODE_CLASS (TREE_CODE (t)))
+ switch (TREE_CODE_CLASS (code))
{
case 'd': /* A decl node. */
ggc_mark_string (DECL_SOURCE_FILE (t));
@@ -469,3 +489,74 @@ ggc_alloc_string (contents, length)
return string;
}
+
+/* Print statistics that are independent of the collector in use. */
+
+void
+ggc_print_statistics (stream, stats)
+ FILE *stream;
+ ggc_statistics *stats;
+{
+ int code;
+
+ /* Set the pointer so that during collection we will actually gather
+ the statistics. */
+ ggc_stats = stats;
+
+ /* Then do one collection to fill in the statistics. */
+ ggc_collect ();
+
+ /* Total the statistics. */
+ for (code = 0; code < MAX_TREE_CODES; ++code)
+ {
+ stats->total_num_trees += stats->num_trees[code];
+ stats->total_size_trees += stats->size_trees[code];
+ }
+ for (code = 0; code < NUM_RTX_CODE; ++code)
+ {
+ stats->total_num_rtxs += stats->num_rtxs[code];
+ stats->total_size_rtxs += stats->size_rtxs[code];
+ }
+
+ /* Print the statistics for trees. */
+ fprintf (stream, "%-22s%-16s%-16s%-7s\n", "Code",
+ "Number", "Bytes", "% Total");
+ for (code = 0; code < MAX_TREE_CODES; ++code)
+ if (ggc_stats->num_trees[code])
+ {
+ fprintf (stream, "%s%*s%-15u %-15u %7.3f\n",
+ tree_code_name[code],
+ 22 - strlen (tree_code_name[code]), "",
+ ggc_stats->num_trees[code],
+ ggc_stats->size_trees[code],
+ (100 * ((double) ggc_stats->size_trees[code])
+ / ggc_stats->total_size_trees));
+ }
+ fprintf (stream,
+ "%-22s%-15u %-15u\n", "Total",
+ ggc_stats->total_num_trees,
+ ggc_stats->total_size_trees);
+
+ /* Print the statistics for RTL. */
+ fprintf (stream, "\n%-22s%-16s%-16s%-7s\n", "Code",
+ "Number", "Bytes", "% Total");
+ for (code = 0; code < NUM_RTX_CODE; ++code)
+ if (ggc_stats->num_rtxs[code])
+ {
+ fprintf (stream, "%s%*s%-15u %-15u %7.3f\n",
+ rtx_name[code],
+ 22 - strlen (rtx_name[code]), "",
+ ggc_stats->num_rtxs[code],
+ ggc_stats->size_rtxs[code],
+ (100 * ((double) ggc_stats->size_rtxs[code])
+ / ggc_stats->total_size_rtxs));
+ }
+ fprintf (stream,
+ "%-22s%-15u %-15u\n", "Total",
+ ggc_stats->total_num_rtxs,
+ ggc_stats->total_size_rtxs);
+
+
+ /* Don't gather statistics any more. */
+ ggc_stats = NULL;
+}
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index f034a4fb47f..c1cef10a5fc 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -226,6 +226,9 @@ static struct globals
/* Bytes currently allocated at the end of the last collection. */
size_t allocated_last_gc;
+ /* Total amount of memory mapped. */
+ size_t bytes_mapped;
+
/* The current depth in the context stack. */
unsigned char context_depth;
@@ -444,6 +447,9 @@ alloc_anon (pref, size)
#endif /* HAVE_VALLOC */
#endif /* HAVE_MMAP */
+ /* Remember that we allocated this memory. */
+ G.bytes_mapped += size;
+
return page;
}
@@ -565,6 +571,7 @@ release_pages ()
else
{
munmap (start, len);
+ G.bytes_mapped -= len;
start = p->page;
len = p->bytes;
}
@@ -573,6 +580,7 @@ release_pages ()
}
munmap (start, len);
+ G.bytes_mapped -= len;
#else
#ifdef HAVE_VALLOC
page_entry *p, *next;
@@ -581,6 +589,7 @@ release_pages ()
{
next = p->next;
free (p->page);
+ G.bytes_mapped -= p->bytes;
free (p);
}
#endif /* HAVE_VALLOC */
@@ -778,6 +787,14 @@ ggc_mark_if_gcable (p)
if (p && ggc_allocated_p (p))
ggc_set_mark (p);
}
+
+size_t
+ggc_get_size (p)
+ void *p;
+{
+ page_entry *pe = lookup_page_table_entry (p);
+ return 1 << pe->order;
+}
/* Initialize the ggc-mmap allocator. */
void
@@ -1088,3 +1105,51 @@ ggc_collect ()
(unsigned long) G.allocated / 1024, time * 1e-6);
}
}
+
+/* Print allocation statistics. */
+
+void
+ggc_page_print_statistics ()
+{
+ struct ggc_statistics stats;
+ int i;
+
+ /* Clear the statistics. */
+ bzero (&stats, sizeof (stats));
+
+ /* Make sure collection will really occur. */
+ G.allocated_last_gc = 0;
+
+ /* Collect and print the statistics common across collectors. */
+ ggc_print_statistics (stderr, &stats);
+
+ /* Collect some information about the various sizes of
+ allocation. */
+ fprintf (stderr, "\n%-4s%-16s%-16s\n", "Log", "Allocated", "Used");
+ for (i = 0; i < HOST_BITS_PER_PTR; ++i)
+ {
+ page_entry *p;
+ size_t allocated;
+ size_t in_use;
+
+ /* Skip empty entries. */
+ if (!G.pages[i])
+ continue;
+
+ allocated = in_use = 0;
+
+ /* Figure out the total number of bytes allocated for objects of
+ this size, and how many of them are actually in use. */
+ for (p = G.pages[i]; p; p = p->next)
+ {
+ allocated += p->bytes;
+ in_use +=
+ (OBJECTS_PER_PAGE (i) - p->num_free_objects) * (1 << i);
+ }
+ fprintf (stderr, "%-3d %-15u %-15u\n", i, allocated, in_use);
+ }
+
+ /* Print out some global information. */
+ fprintf (stderr, "\nTotal bytes marked: %u\n", G.allocated);
+ fprintf (stderr, "Total bytes mapped: %u\n", G.bytes_mapped);
+}
diff --git a/gcc/ggc-simple.c b/gcc/ggc-simple.c
index f665487cd53..194863edc7d 100644
--- a/gcc/ggc-simple.c
+++ b/gcc/ggc-simple.c
@@ -253,6 +253,15 @@ ggc_mark_if_gcable (p)
G.objects += 1;
}
+size_t
+ggc_get_size (p)
+ void *p;
+{
+ struct ggc_mem *x
+ = (struct ggc_mem *) ((char *)p - offsetof (struct ggc_mem, u));
+ return x->size;
+}
+
static void
clear_marks (x)
struct ggc_mem *x;
diff --git a/gcc/ggc.h b/gcc/ggc.h
index b2cfb279a5c..2c12a139935 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -165,3 +165,36 @@ void mark_expr_status PROTO ((struct expr_status *));
void mark_stmt_status PROTO ((struct stmt_status *));
void mark_varasm_status PROTO ((struct varasm_status *));
void mark_optab PROTO ((void *));
+
+/* Statistics. */
+
+/* This structure contains the statistics common to all collectors.
+ Particular collectors can extend this structure. */
+typedef struct ggc_statistics
+{
+ /* The Ith element is the number of nodes allocated with code I. */
+ unsigned num_trees[256];
+ /* The Ith element is the number of bytes allocated by nodes with
+ code I. */
+ size_t size_trees[256];
+ /* The Ith element is the number of nodes allocated with code I. */
+ unsigned num_rtxs[256];
+ /* The Ith element is the number of bytes allocated by nodes with
+ code I. */
+ size_t size_rtxs[256];
+ /* The total number of tree nodes allocated. */
+ unsigned total_num_trees;
+ /* The total size of the tree nodes allocated. */
+ size_t total_size_trees;
+ /* The total number of RTL nodes allocated. */
+ unsigned total_num_rtxs;
+ /* The total size of the RTL nodes allocated. */
+ size_t total_size_rtxs;
+} ggc_statistics;
+
+/* Return the number of bytes allocated at the indicated address. */
+size_t ggc_get_size PROTO ((void *));
+
+/* Used by the various collectors to gather and print statistics that
+ do not depend on the collector in use. */
+void ggc_print_statistics PROTO ((FILE *, ggc_statistics *));