aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2009-09-28 10:50:39 +0200
committerDuncan Sands <baldrick@gcc.gnu.org>2009-09-28 08:50:39 +0000
commit32c9b4e92473a94323f4198c4fc2a34f6052f30e (patch)
tree194a436e90764acef2d9ddd4041e1b96fecade5a
parentbd77e02dac3326a073283468832c6e5bb66291bf (diff)
downloadgcc-32c9b4e92473a94323f4198c4fc2a34f6052f30e.zip
gcc-32c9b4e92473a94323f4198c4fc2a34f6052f30e.tar.gz
gcc-32c9b4e92473a94323f4198c4fc2a34f6052f30e.tar.bz2
Add support for using ggc cache tables from plugins.
Approved by Ian Lance Taylor. From-SVN: r152232
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/doc/plugins.texi24
-rw-r--r--gcc/gcc-plugin.h5
-rw-r--r--gcc/ggc-common.c83
-rw-r--r--gcc/ggc.h6
-rw-r--r--gcc/plugin.c6
6 files changed, 94 insertions, 45 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d1e8737..51a580b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2009-09-27 Duncan Sands <baldrick@free.fr>
+
+ * gcc-plugin.h (PLUGIN_REGISTER_GGC_CACHES): New event.
+ * plugin.c (plugin_event_name): Add PLUGIN_REGISTER_GGC_CACHES.
+ (register_callback): Dispatch it.
+ (invoke_plugin_callbacks): Incorporate in sanity check.
+ * ggc.h (ggc_register_cache_tab): Add declaration.
+ * ggc-common.c (ggc_register_root_tab): Simplify.
+ (const_ggc_cache_tab_t): New typedef.
+ (extra_cache_vec): New vector of dynamically added cache tables.
+ (ggc_register_cache_tab): New function.
+ (ggc_scan_cache_tab): New function.
+ (ggc_mark_roots): Simplify dynamic roots. Handle dynamic caches.
+ * doc/plugins.texi: Document PLUGIN_REGISTER_GGC_CACHES.
+
2009-09-27 Richard Henderson <rth@redhat.com>
* tree-ssa-ccp.c (optimize_stack_restore): Relax the conditions under
diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
index 4dfb159..bb32bcc 100644
--- a/gcc/doc/plugins.texi
+++ b/gcc/doc/plugins.texi
@@ -133,6 +133,7 @@ enum plugin_event
PLUGIN_GGC_MARKING, /* Extend the GGC marking. */
PLUGIN_GGC_END, /* Called at end of GGC. */
PLUGIN_REGISTER_GGC_ROOTS, /* Register an extra GGC root table. */
+ PLUGIN_REGISTER_GGC_CACHES, /* Register an extra GGC cache table. */
PLUGIN_ATTRIBUTES, /* Called during attribute registration */
PLUGIN_START_UNIT, /* Called before processing a translation unit. */
PLUGIN_EVENT_LAST /* Dummy event used for indexing callback
@@ -151,8 +152,8 @@ the arguments:
@item @code{void *user_data}: Pointer to plugin-specific data.
@end itemize
-For the PLUGIN_PASS_MANAGER_SETUP, PLUGIN_INFO, and
-PLUGIN_REGISTER_GGC_ROOTS pseudo-events the @code{callback} should be
+For the PLUGIN_PASS_MANAGER_SETUP, PLUGIN_INFO, PLUGIN_REGISTER_GGC_ROOTS
+and PLUGIN_REGISTER_GGC_CACHES pseudo-events the @code{callback} should be
null, and the @code{user_data} is specific.
@section Interacting with the pass manager
@@ -222,16 +223,19 @@ for the @code{PLUGIN_GGC_MARKING} event. Such callbacks can call the
(and conversely, these routines should usually not be used in plugins
outside of the @code{PLUGIN_GGC_MARKING} event).
-Some plugins may need to add extra GGC root tables, e.g. to handle
-their own @code{GTY}-ed data. This can be done with the
-@code{PLUGIN_REGISTER_GGC_ROOTS} pseudo-event with a null callback and
-the extra root table as @code{user_data}. Running the @code{gengtype
--p @var{source-dir} @var{file-list} @var{plugin*.c} ...} utility
-generates this extra root table.
+Some plugins may need to add extra GGC root tables, e.g. to handle their own
+@code{GTY}-ed data. This can be done with the @code{PLUGIN_REGISTER_GGC_ROOTS}
+pseudo-event with a null callback and the extra root table (of type @code{struct
+ggc_root_tab*}) as @code{user_data}. Plugins that want to use the
+@code{if_marked} hash table option can add the extra GGC cache tables generated
+by @code{gengtype} using the @code{PLUGIN_REGISTER_GGC_CACHES} pseudo-event with
+a null callback and the extra cache table (of type @code{struct ggc_cache_tab*})
+as @code{user_data}. Running the @code{gengtype -p @var{source-dir}
+@var{file-list} @var{plugin*.c} ...} utility generates these extra root tables.
You should understand the details of memory management inside GCC
-before using @code{PLUGIN_GGC_MARKING} or
-@code{PLUGIN_REGISTER_GGC_ROOTS}.
+before using @code{PLUGIN_GGC_MARKING}, @code{PLUGIN_REGISTER_GGC_ROOTS}
+or @code{PLUGIN_REGISTER_GGC_CACHES}.
@section Giving information about a plugin
diff --git a/gcc/gcc-plugin.h b/gcc/gcc-plugin.h
index 9fbdc91..84f0aed 100644
--- a/gcc/gcc-plugin.h
+++ b/gcc/gcc-plugin.h
@@ -40,6 +40,7 @@ enum plugin_event
PLUGIN_GGC_MARKING, /* Extend the GGC marking. */
PLUGIN_GGC_END, /* Called at end of GGC. */
PLUGIN_REGISTER_GGC_ROOTS, /* Register an extra GGC root table. */
+ PLUGIN_REGISTER_GGC_CACHES, /* Register an extra GGC cache table. */
PLUGIN_ATTRIBUTES, /* Called during attribute registration. */
PLUGIN_START_UNIT, /* Called before processing a translation unit. */
PLUGIN_EVENT_LAST /* Dummy event used for indexing callback
@@ -144,8 +145,8 @@ typedef void (*plugin_callback_func) (void *gcc_data, void *user_data);
*/
/* This is also called without a callback routine for the
- PLUGIN_PASS_MANAGER_SETUP, PLUGIN_INFO, PLUGIN_REGISTER_GGC_ROOTS
- pseudo-events, with a specific user_data.
+ PLUGIN_PASS_MANAGER_SETUP, PLUGIN_INFO, PLUGIN_REGISTER_GGC_ROOTS and
+ PLUGIN_REGISTER_GGC_CACHES pseudo-events, with a specific user_data.
*/
extern void register_callback (const char *plugin_name,
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index 2499ff5..76a35f7 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -91,30 +91,59 @@ ggc_htab_delete (void **slot, void *info)
/* This extra vector of dynamically registered root_tab-s is used by
ggc_mark_roots and gives the ability to dynamically add new GGC root
- tables, for instance from some plugins; this vector is a heap one
- [since it is used by GGC internally!] */
-typedef const struct ggc_root_tab* const_ggc_root_tab_t;
+ tables, for instance from some plugins; this vector is on the heap
+ since it is used by GGC internally. */
+typedef const struct ggc_root_tab *const_ggc_root_tab_t;
DEF_VEC_P(const_ggc_root_tab_t);
DEF_VEC_ALLOC_P(const_ggc_root_tab_t, heap);
static VEC(const_ggc_root_tab_t, heap) *extra_root_vec;
-
/* Dynamically register a new GGC root table RT. This is useful for
plugins. */
void
ggc_register_root_tab (const struct ggc_root_tab* rt)
{
- if (!rt)
- return;
- if (!extra_root_vec)
- {
- int vlen = 32;
- extra_root_vec = VEC_alloc (const_ggc_root_tab_t, heap, vlen);
- }
- VEC_safe_push (const_ggc_root_tab_t, heap, extra_root_vec, rt);
+ if (rt)
+ VEC_safe_push (const_ggc_root_tab_t, heap, extra_root_vec, rt);
+}
+
+/* This extra vector of dynamically registered cache_tab-s is used by
+ ggc_mark_roots and gives the ability to dynamically add new GGC cache
+ tables, for instance from some plugins; this vector is on the heap
+ since it is used by GGC internally. */
+typedef const struct ggc_cache_tab *const_ggc_cache_tab_t;
+DEF_VEC_P(const_ggc_cache_tab_t);
+DEF_VEC_ALLOC_P(const_ggc_cache_tab_t, heap);
+static VEC(const_ggc_cache_tab_t, heap) *extra_cache_vec;
+
+/* Dynamically register a new GGC cache table CT. This is useful for
+ plugins. */
+
+void
+ggc_register_cache_tab (const struct ggc_cache_tab* ct)
+{
+ if (ct)
+ VEC_safe_push (const_ggc_cache_tab_t, heap, extra_cache_vec, ct);
}
+/* Scan a hash table that has objects which are to be deleted if they are not
+ already marked. */
+
+static void
+ggc_scan_cache_tab (const_ggc_cache_tab_t ctp)
+{
+ const struct ggc_cache_tab *cti;
+
+ for (cti = ctp; cti->base != NULL; cti++)
+ if (*cti->base)
+ {
+ ggc_set_mark (*cti->base);
+ htab_traverse_noresize (*cti->base, ggc_htab_delete,
+ CONST_CAST (void *, (const void *)cti));
+ ggc_set_mark ((*cti->base)->entries);
+ }
+}
/* Iterate through all registered roots and mark each element. */
@@ -123,8 +152,9 @@ ggc_mark_roots (void)
{
const struct ggc_root_tab *const *rt;
const struct ggc_root_tab *rti;
+ const_ggc_root_tab_t rtp;
const struct ggc_cache_tab *const *ct;
- const struct ggc_cache_tab *cti;
+ const_ggc_cache_tab_t ctp;
size_t i;
for (rt = gt_ggc_deletable_rtab; *rt; rt++)
@@ -136,18 +166,11 @@ ggc_mark_roots (void)
for (i = 0; i < rti->nelt; i++)
(*rti->cb) (*(void **)((char *)rti->base + rti->stride * i));
- if (extra_root_vec
- && VEC_length(const_ggc_root_tab_t,extra_root_vec) > 0)
+ for (i = 0; VEC_iterate (const_ggc_root_tab_t, extra_root_vec, i, rtp); i++)
{
- const_ggc_root_tab_t rtp = NULL;
- for (i=0;
- VEC_iterate(const_ggc_root_tab_t, extra_root_vec, i, rtp);
- i++)
- {
- for (rti = rtp; rti->base != NULL; rti++)
- for (i = 0; i < rti->nelt; i++)
- (*rti->cb) (*(void **) ((char *)rti->base + rti->stride * i));
- }
+ for (rti = rtp; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ (*rti->cb) (*(void **) ((char *)rti->base + rti->stride * i));
}
if (ggc_protect_identifiers)
@@ -156,14 +179,10 @@ ggc_mark_roots (void)
/* Now scan all hash tables that have objects which are to be deleted if
they are not already marked. */
for (ct = gt_ggc_cache_rtab; *ct; ct++)
- for (cti = *ct; cti->base != NULL; cti++)
- if (*cti->base)
- {
- ggc_set_mark (*cti->base);
- htab_traverse_noresize (*cti->base, ggc_htab_delete,
- CONST_CAST (void *, (const void *)cti));
- ggc_set_mark ((*cti->base)->entries);
- }
+ ggc_scan_cache_tab (*ct);
+
+ for (i = 0; VEC_iterate (const_ggc_cache_tab_t, extra_cache_vec, i, ctp); i++)
+ ggc_scan_cache_tab (ctp);
if (! ggc_protect_identifiers)
ggc_purge_stringpool ();
diff --git a/gcc/ggc.h b/gcc/ggc.h
index e3471e4..c373de3 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -272,9 +272,13 @@ extern const char *ggc_alloc_string (const char *contents, int length);
extern void ggc_collect (void);
/* Register an additional root table. This can be useful for some
- plugins. Does nothing if the passed pointer is null. */
+ plugins. Does nothing if the passed pointer is NULL. */
extern void ggc_register_root_tab (const struct ggc_root_tab *);
+/* Register an additional cache table. This can be useful for some
+ plugins. Does nothing if the passed pointer is NULL. */
+extern void ggc_register_cache_tab (const struct ggc_cache_tab *);
+
/* Return the number of bytes allocated at the indicated address. */
extern size_t ggc_get_size (const void *);
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 9060683..7d6e85f 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -57,6 +57,7 @@ const char *plugin_event_name[] =
"PLUGIN_GGC_MARKING",
"PLUGIN_GGC_END",
"PLUGIN_REGISTER_GGC_ROOTS",
+ "PLUGIN_REGISTER_GGC_CACHES",
"PLUGIN_START_UNIT",
"PLUGIN_EVENT_LAST"
};
@@ -499,6 +500,10 @@ register_callback (const char *plugin_name,
gcc_assert (!callback);
ggc_register_root_tab ((const struct ggc_root_tab*) user_data);
break;
+ case PLUGIN_REGISTER_GGC_CACHES:
+ gcc_assert (!callback);
+ ggc_register_cache_tab ((const struct ggc_cache_tab*) user_data);
+ break;
case PLUGIN_FINISH_TYPE:
case PLUGIN_START_UNIT:
case PLUGIN_FINISH_UNIT:
@@ -566,6 +571,7 @@ invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
case PLUGIN_PASS_MANAGER_SETUP:
case PLUGIN_EVENT_LAST:
case PLUGIN_REGISTER_GGC_ROOTS:
+ case PLUGIN_REGISTER_GGC_CACHES:
default:
gcc_assert (false);
}