summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/ggc-page.c14
-rw-r--r--gcc/ggc-simple.c14
-rw-r--r--gcc/ggc-zone.c123
-rw-r--r--gcc/ggc.h11
5 files changed, 128 insertions, 51 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b93d8aa9285..0507e0d6791 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+2003-12-01 Steven Bosscher <stevenb@suse.de>
+
+ * ggc.h (struct alloc_zone): Move forward declaration up.
+ (new_ggc_zone): New function prototype.
+ (destroy_ggc_zone): Ditto.
+ * ggc-simple.c (new_ggc_zone): New function, does nothing.
+ (destroy_ggc_zone): Ditto.
+ * ggc-page.c (new_ggc_zone): New function, does nothing.
+ (destroy_ggc_zone): Ditto.
+ * ggc-zone.c (struct page_entry): Fix comment.
+ (ggc_alloc_typed): Use a switch statement instead of ifs.
+ (new_ggc_zone): New function to set up a new GC zone.
+ (destroy_ggc_zone): New function to remove a GC zone.
+ init_ggc): Use new_ggc_zone to set up the default zones.
+ (ggc_collect): Walk a list of zones, instead of just the
+ default zones. Report statistics using the zone name.
+
2003-12-01 Ulrich Weigand <uweigand@de.ibm.com>
* unroll.c (find_splittable_givs): Add missing extend_value_for_giv.
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 12b1f17b265..7e40d044535 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -1401,6 +1401,20 @@ init_ggc (void)
G.save_in_use = xmalloc (G.by_depth_max * sizeof (unsigned long *));
}
+/* Start a new GGC zone. */
+
+struct alloc_zone *
+new_ggc_zone (const char *name ATTRIBUTE_UNUSED)
+{
+ return NULL;
+}
+
+/* Destroy a GGC zone. */
+void
+destroy_ggc_zone (struct alloc_zone *zone ATTRIBUTE_UNUSED)
+{
+}
+
/* Increment the `GC context'. Objects allocated in an outer context
are never freed, eliminating the need to register their roots. */
diff --git a/gcc/ggc-simple.c b/gcc/ggc-simple.c
index eee33a568af..2f75021f42d 100644
--- a/gcc/ggc-simple.c
+++ b/gcc/ggc-simple.c
@@ -344,6 +344,20 @@ init_ggc (void)
{
}
+/* Start a new GGC zone. */
+
+struct alloc_zone *
+new_ggc_zone (const char *name ATTRIBUTE_UNUSED)
+{
+ return NULL;
+}
+
+/* Destroy a GGC zone. */
+void
+destroy_ggc_zone (struct alloc_zone *zone ATTRIBUTE_UNUSED)
+{
+}
+
/* Start a new GGC context. Memory allocated in previous contexts
will not be collected while the new context is active. */
diff --git a/gcc/ggc-zone.c b/gcc/ggc-zone.c
index d9c82e6c696..4aee63852b2 100644
--- a/gcc/ggc-zone.c
+++ b/gcc/ggc-zone.c
@@ -277,6 +277,7 @@ typedef struct page_entry
/* Does this page contain small objects, or one large object? */
bool large_p;
+ /* The zone that this page entry belongs to. */
struct alloc_zone *zone;
} page_entry;
@@ -1007,14 +1008,20 @@ ggc_alloc_zone_1 (size_t size, struct alloc_zone *zone, short type)
void *
ggc_alloc_typed (enum gt_types_enum gte, size_t size)
{
- if (gte == gt_ggc_e_14lang_tree_node)
- return ggc_alloc_zone_1 (size, tree_zone, gte);
- else if (gte == gt_ggc_e_7rtx_def)
- return ggc_alloc_zone_1 (size, rtl_zone, gte);
- else if (gte == gt_ggc_e_9rtvec_def)
- return ggc_alloc_zone_1 (size, rtl_zone, gte);
- else
- return ggc_alloc_zone_1 (size, &main_zone, gte);
+ switch (gte)
+ {
+ case gt_ggc_e_14lang_tree_node:
+ return ggc_alloc_zone_1 (size, tree_zone, gte);
+
+ case gt_ggc_e_7rtx_def:
+ return ggc_alloc_zone_1 (size, rtl_zone, gte);
+
+ case gt_ggc_e_9rtvec_def:
+ return ggc_alloc_zone_1 (size, rtl_zone, gte);
+
+ default:
+ return ggc_alloc_zone_1 (size, &main_zone, gte);
+ }
}
/* Normal ggc_alloc simply allocates into the main zone. */
@@ -1135,24 +1142,14 @@ ggc_get_size (const void *p)
void
init_ggc (void)
{
- /* Create the zones. */
+ /* Set up the main zone by hand. */
main_zone.name = "Main zone";
G.zones = &main_zone;
- rtl_zone = xcalloc (1, sizeof (struct alloc_zone));
- rtl_zone->name = "RTL zone";
- /* The main zone's connected to the ... rtl_zone */
- G.zones->next_zone = rtl_zone;
-
- garbage_zone = xcalloc (1, sizeof (struct alloc_zone));
- garbage_zone->name = "Garbage zone";
- /* The rtl zone's connected to the ... garbage zone */
- rtl_zone->next_zone = garbage_zone;
-
- tree_zone = xcalloc (1, sizeof (struct alloc_zone));
- tree_zone->name = "Tree zone";
- /* The garbage zone's connected to ... the tree zone */
- garbage_zone->next_zone = tree_zone;
+ /* Allocate the default zones. */
+ rtl_zone = new_ggc_zone ("RTL zone");
+ tree_zone = new_ggc_zone ("Tree zone");
+ garbage_zone = new_ggc_zone ("Garbage zone");
G.pagesize = getpagesize();
G.lg_pagesize = exact_log2 (G.pagesize);
@@ -1197,6 +1194,40 @@ init_ggc (void)
#endif
}
+/* Start a new GGC zone. */
+
+struct alloc_zone *
+new_ggc_zone (const char * name)
+{
+ struct alloc_zone *new_zone = xcalloc (1, sizeof (struct alloc_zone));
+ new_zone->name = name;
+ new_zone->next_zone = G.zones->next_zone;
+ G.zones->next_zone = new_zone;
+ return new_zone;
+}
+
+/* Destroy a GGC zone. */
+void
+destroy_ggc_zone (struct alloc_zone * dead_zone)
+{
+ struct alloc_zone *z;
+
+ for (z = G.zones; z && z->next_zone != dead_zone; z = z->next_zone)
+ /* Just find that zone. */ ;
+
+ /* We should have found the zone in the list. Anything else is
+ fatal.
+ If we did find the zone, we expect this zone to be empty.
+ A ggc_collect should have emptied it before we can destroy it. */
+ if (!z || dead_zone->allocated != 0)
+ abort ();
+
+ /* Unchain the dead zone, release all its pages and free it. */
+ z->next_zone = z->next_zone->next_zone;
+ release_pages (dead_zone);
+ free (dead_zone);
+}
+
/* Increment the `GC context'. Objects allocated in an outer context
are never freed, eliminating the need to register their roots. */
@@ -1234,9 +1265,9 @@ ggc_pop_context_1 (struct alloc_zone *zone)
/* Any remaining pages in the popped context are lowered to the new
current context; i.e. objects allocated in the popped context and
left over are imported into the previous context. */
- for (p = zone->pages; p != NULL; p = p->next)
- if (p->context_depth > depth)
- p->context_depth = depth;
+ for (p = zone->pages; p != NULL; p = p->next)
+ if (p->context_depth > depth)
+ p->context_depth = depth;
}
/* Pop all the zone contexts. */
@@ -1478,6 +1509,7 @@ ggc_collect (void)
/* Start by possibly collecting the main zone. */
main_zone.was_collected = false;
marked |= ggc_collect_1 (&main_zone, true);
+
/* In order to keep the number of collections down, we don't
collect other zones unless we are collecting the main zone. This
gives us roughly the same number of collections as we used to
@@ -1489,36 +1521,30 @@ ggc_collect (void)
if (main_zone.was_collected)
{
- check_cookies ();
- rtl_zone->was_collected = false;
- marked |= ggc_collect_1 (rtl_zone, !marked);
- check_cookies ();
- tree_zone->was_collected = false;
- marked |= ggc_collect_1 (tree_zone, !marked);
- check_cookies ();
- garbage_zone->was_collected = false;
- marked |= ggc_collect_1 (garbage_zone, !marked);
+ struct alloc_zone *zone;
+
+ for (zone = main_zone.next_zone; zone; zone = zone->next_zone)
+ {
+ check_cookies ();
+ zone->was_collected = false;
+ marked |= ggc_collect_1 (zone, !marked);
+ }
}
/* Print page survival stats, if someone wants them. */
if (GGC_DEBUG_LEVEL >= 2)
{
- if (rtl_zone->was_collected)
- {
- f = calculate_average_page_survival (rtl_zone);
- printf ("Average RTL page survival is %f\n", f);
- }
- if (main_zone.was_collected)
- {
- f = calculate_average_page_survival (&main_zone);
- printf ("Average main page survival is %f\n", f);
- }
- if (tree_zone->was_collected)
+ for (zone = G.zones; zone; zone = zone->next_zone)
{
- f = calculate_average_page_survival (tree_zone);
- printf ("Average tree page survival is %f\n", f);
+ if (zone->was_collected)
+ {
+ f = calculate_average_page_survival (zone);
+ printf ("Average page survival in zone `%s' is %f\n",
+ zone->name, f);
+ }
}
}
+
/* Since we don't mark zone at a time right now, marking in any
zone means marking in every zone. So we have to clear all the
marks in all the zones that weren't collected already. */
@@ -1578,7 +1604,6 @@ struct ggc_pch_data
} d;
size_t base;
size_t written;
-
};
/* Initialize the PCH datastructure. */
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 4f25f7373c2..3a8b57e4aba 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -141,9 +141,18 @@ extern void init_stringpool (void);
/* A GC implementation must provide these functions. They are internal
to the GC system. */
+/* Forward declare the zone structure. Only ggc_zone implements this. */
+struct alloc_zone;
+
/* Initialize the garbage collector. */
extern void init_ggc (void);
+/* Start a new GGC zone. */
+extern struct alloc_zone *new_ggc_zone (const char *);
+
+/* Free a complete GGC zone, destroying everything in it. */
+extern void destroy_ggc_zone (struct alloc_zone *);
+
/* Start a new GGC context. Memory allocated in previous contexts
will not be collected while the new context is active. */
extern void ggc_push_context (void);
@@ -193,8 +202,6 @@ extern void ggc_pch_read (FILE *, void *);
/* Allocation. */
-/* Zone structure. */
-struct alloc_zone;
/* For single pass garbage. */
extern struct alloc_zone *garbage_zone;
/* For regular rtl allocations. */