diff options
author | baldrick <baldrick@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-28 08:50:39 +0000 |
---|---|---|
committer | baldrick <baldrick@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-28 08:50:39 +0000 |
commit | 86b6369622fb5ab4b0fc6e5bd2ff40cb25ad4166 (patch) | |
tree | 194a436e90764acef2d9ddd4041e1b96fecade5a | |
parent | 634c15dc444b793c959353a4cb61294ca30fda9c (diff) | |
download | gcc-86b6369622fb5ab4b0fc6e5bd2ff40cb25ad4166.tar.gz |
Add support for using ggc cache tables from plugins.
Approved by Ian Lance Taylor.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@152232 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/doc/plugins.texi | 24 | ||||
-rw-r--r-- | gcc/gcc-plugin.h | 5 | ||||
-rw-r--r-- | gcc/ggc-common.c | 83 | ||||
-rw-r--r-- | gcc/ggc.h | 6 | ||||
-rw-r--r-- | gcc/plugin.c | 6 |
6 files changed, 94 insertions, 45 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d1e87371b81..51a580bc7a5 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 4dfb159c883..bb32bccbf18 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 9fbdc91af25..84f0aedb1b3 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 2499ff51cd7..76a35f7e029 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 e3471e45353..c373de32cb7 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 906068387b7..7d6e85f9cef 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); } |