From: mmitchel Date: Fri, 29 Oct 1999 04:17:33 +0000 (+0000) Subject: * ggc.h (struct ggc_statistics): New type. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4e00b6fd23bf82e4038e115609361fb0c62465f7;p=platform%2Fupstream%2Flinaro-gcc.git * 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 97e54f5..aeb66bf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +Thu Oct 28 21:16:35 1999 Mark Mitchell + + * 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 * flow.c (propagate_block): When the last reference to a label diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c index 2d8631d..fdc0322 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 f034a4f..c1cef10 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 f665487..194863e 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 b2cfb27..2c12a13 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 *));