* ggc.h (ggc_push_context): Fix comment.
(ggc_pop_context): Likewise.
(mark_string_if_gcable): Likewise.
* ggc-common.c (ggc_mark_rtx_children): Use
ggc_mark_string_if_gcable.
* ggc-page.c (ggc_lookup_page_table): New function.
(ggc_allocated_p): Likewise.
(mark_obj): Fix formatting.
(ggc_mark_string_if_gcable): New function.
* ggc-simple.c (ggc_allocated_strings): New variable.
(ggc_strings_used): Likewise.
(ggc_compare_addresses): New function.
(ggc_pop_context): Pop the `any' memory too.
(ggc_mark_string_if_gcable): New function.
(ggc_collect): Initialize and tear down ggc_allocated_strings.
From-SVN: r29897
+Sun Oct 10 18:27:27 1999 Mark Mitchell <mark@codesourcery.com>
+
+ * ggc.h (ggc_push_context): Fix comment.
+ (ggc_pop_context): Likewise.
+ (mark_string_if_gcable): Likewise.
+ * ggc-common.c (ggc_mark_rtx_children): Use
+ ggc_mark_string_if_gcable.
+ * ggc-page.c (ggc_lookup_page_table): New function.
+ (ggc_allocated_p): Likewise.
+ (mark_obj): Fix formatting.
+ (ggc_mark_string_if_gcable): New function.
+ * ggc-simple.c (ggc_allocated_strings): New variable.
+ (ggc_strings_used): Likewise.
+ (ggc_compare_addresses): New function.
+ (ggc_pop_context): Pop the `any' memory too.
+ (ggc_mark_string_if_gcable): New function.
+ (ggc_collect): Initialize and tear down ggc_allocated_strings.
+
Sun Oct 10 20:05:21 1999 David Edelsohn <edelsohn@gnu.org>
* rs6000.md (movstrsi_?reg): Use preferred rD/rS = r5 form.
ggc_mark_rtvec (XVEC (r, i));
break;
case 'S': case 's':
- ggc_mark_string (XSTR (r, i));
+ ggc_mark_string_if_gcable (XSTR (r, i));
break;
}
}
#define GGC_MIN_LAST_ALLOCATED (4 * 1024 * 1024)
\f
+static page_entry *** ggc_lookup_page_table PROTO ((void));
+static int ggc_allocated_p PROTO ((const void *));
static page_entry *lookup_page_table_entry PROTO ((void *));
static void set_page_table_entry PROTO ((void *, page_entry *));
static char *alloc_anon PROTO ((char *, size_t));
void debug_print_page_list PROTO ((int));
\f
-/* Traverse the page table and find the entry for a page.
- Die (probably) if the object wasn't allocated via GC. */
+/* Returns the lookup table appropriate for looking up P. */
-static inline page_entry *
-lookup_page_table_entry(p)
- void *p;
+static inline page_entry ***
+ggc_lookup_page_table ()
{
page_entry ***base;
- size_t L1, L2;
#if HOST_BITS_PER_PTR <= 32
base = &G.lookup[0];
base = &table->table[0];
#endif
+ return base;
+}
+
+/* Returns non-zero if P was allocated in GC'able memory. */
+
+static inline int
+ggc_allocated_p (p)
+ const void *p;
+{
+ page_entry ***base;
+ size_t L1, L2;
+
+ base = ggc_lookup_page_table ();
+
+ /* Extract the level 1 and 2 indicies. */
+ L1 = LOOKUP_L1 (p);
+ L2 = LOOKUP_L2 (p);
+
+ return base[L1] && base[L1][L2];
+}
+
+/* Traverse the page table and find the entry for a page.
+ Die (probably) if the object wasn't allocated via GC. */
+
+static inline page_entry *
+lookup_page_table_entry(p)
+ void *p;
+{
+ page_entry ***base;
+ size_t L1, L2;
+
+ base = ggc_lookup_page_table ();
+
/* Extract the level 1 and 2 indicies. */
L1 = LOOKUP_L1 (p);
L2 = LOOKUP_L2 (p);
/* Look up the page on which the object is alloced. If the object
wasn't allocated by the collector, we'll probably die. */
- entry = lookup_page_table_entry(p);
+ entry = lookup_page_table_entry (p);
#ifdef ENABLE_CHECKING
if (entry == NULL)
abort ();
mark_obj (s);
}
+void
+ggc_mark_string_if_gcable (s)
+ char *s;
+{
+ if (s && ggc_allocated_p (s))
+ mark_obj (s);
+}
+
void
ggc_mark (p)
void *p;
front of the chain. */
static struct ggc_status *ggc_chain;
+/* The table of all allocated strings. Only valid during collection. */
+static varray_type ggc_allocated_strings;
+static size_t ggc_strings_used;
+
/* Some statistics. */
static int n_rtxs_collected;
static void ggc_free_tree PROTO ((struct ggc_tree *t));
static void ggc_free_string PROTO ((struct ggc_string *s));
static void ggc_free_any PROTO ((struct ggc_any *a));
+static int ggc_compare_addresses PROTO ((const void *, const void *));
/* Called once to initialize the garbage collector. */
struct ggc_rtvec *v;
struct ggc_tree *t;
struct ggc_string *s;
+ struct ggc_any *a;
struct ggc_status *gs;
gs = ggc_chain;
gs->next->strings = gs->strings;
}
+ a = gs->anys;
+ if (a)
+ {
+ while (a->chain)
+ a = a->chain;
+ a->chain = gs->next->anys;
+ gs->next->anys = gs->anys;
+ }
+
gs->next->bytes_alloced_since_gc += gs->bytes_alloced_since_gc;
ggc_chain = gs->next;
return marked;
}
+/* Compare the pointers pointed to by A1 and A2. Used as a callback
+ for qsort/bsearch. */
+
+static int
+ggc_compare_addresses (a1, a2)
+ const void *a1;
+ const void *a2;
+{
+ const char *c1 = *((const char **) a1);
+ const char *c2 = *((const char **) a2);
+
+ if (c1 < c2)
+ return -1;
+ else if (c1 > c2)
+ return 1;
+ else
+ return 0;
+}
+
void
ggc_mark_string (s)
char *s;
gs->magic_mark = GGC_STRING_MAGIC_MARK;
}
+
+void
+ggc_mark_string_if_gcable (s)
+ char *s;
+{
+ if (s && !bsearch (&s,
+ &VARRAY_CHAR_PTR (ggc_allocated_strings, 0),
+ ggc_strings_used, sizeof (char *),
+ ggc_compare_addresses))
+ return;
+
+ ggc_mark_string (s);
+}
+
+
/* Mark P, allocated with ggc_alloc. */
void
time = get_run_time ();
+ /* Set up the table of allocated strings. */
+ VARRAY_CHAR_PTR_INIT (ggc_allocated_strings, 1024, "allocated strings");
+ ggc_strings_used = 0;
+
/* Clean out all of the GC marks. */
for (gs = ggc_chain; gs; gs = gs->next)
{
for (t = gs->trees; t != NULL; t = t->chain)
t->tree.common.gc_mark = 0;
for (s = gs->strings; s != NULL; s = s->chain)
- s->magic_mark = GGC_STRING_MAGIC;
+ {
+ s->magic_mark = GGC_STRING_MAGIC;
+ if (ggc_strings_used == ggc_allocated_strings->num_elements)
+ VARRAY_GROW (ggc_allocated_strings, 2 * ggc_strings_used);
+ VARRAY_CHAR_PTR (ggc_allocated_strings, ggc_strings_used)
+ = &s->string[0];
+ ++ggc_strings_used;
+ }
for (a = gs->anys; a != NULL; a = a->chain)
a->magic_mark = GGC_ANY_MAGIC;
}
+ /* Sort the allocated string table. */
+ qsort (&VARRAY_CHAR_PTR (ggc_allocated_strings, 0),
+ ggc_strings_used, sizeof (char *),
+ ggc_compare_addresses);
+
ggc_mark_roots ();
+ /* Free the string table. */
+ VARRAY_FREE (ggc_allocated_strings);
+
/* Sweep the resulting dead nodes. */
/* The RTXs. */
extern void ggc_mark_rtx_children PROTO ((struct rtx_def *));
extern void ggc_mark_tree_children PROTO ((union tree_node *));
+/* Mark the string, but only if it was allocated in collectable
+ memory. */
+extern void ggc_mark_string_if_gcable PROTO ((char *));
+
#define ggc_mark_rtx(RTX_EXPR) \
do { \
rtx r__ = (RTX_EXPR); \
/* Start a new GGC context. Memory allocated in previous contexts
will not be collected while the new context is active. */
-extern void ggc_pop_context PROTO ((void));
+extern void ggc_push_context PROTO ((void));
/* Finish a GC context. Any uncollected memory in the new context
will be merged with the old context. */
-extern void ggc_push_context PROTO ((void));
+extern void ggc_pop_context PROTO ((void));
/* Allocation. */
struct rtx_def *ggc_alloc_rtx PROTO ((int nslots));
int ggc_set_mark_rtvec PROTO ((struct rtvec_def *));
int ggc_set_mark_tree PROTO ((union tree_node *));
-
/* Callbacks to the languages. */
/* This is the language's opportunity to mark nodes held through