OSDN Git Service

2010-04-08 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / ggc-common.c
index 747ec4c..28c2b79 100644 (file)
@@ -30,6 +30,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "params.h"
 #include "hosthooks.h"
 #include "hosthooks-def.h"
+#include "plugin.h"
+#include "vec.h"
+#include "timevar.h"
 
 #ifdef HAVE_SYS_RESOURCE_H
 # include <sys/resource.h>
@@ -39,7 +42,7 @@ along with GCC; see the file COPYING3.  If not see
 # include <sys/mman.h>
 # ifdef HAVE_MINCORE
 /* This is on Solaris.  */
-#  include <sys/types.h> 
+#  include <sys/types.h>
 # endif
 #endif
 
@@ -86,6 +89,63 @@ ggc_htab_delete (void **slot, void *info)
   return 1;
 }
 
+
+/* 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 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)
+    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.  */
 
 void
@@ -93,8 +153,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++)
@@ -104,7 +165,14 @@ ggc_mark_roots (void)
   for (rt = gt_ggc_rtab; *rt; rt++)
     for (rti = *rt; rti->base != NULL; rti++)
       for (i = 0; i < rti->nelt; i++)
-       (*rti->cb)(*(void **)((char *)rti->base + rti->stride * i));
+       (*rti->cb) (*(void **)((char *)rti->base + rti->stride * i));
+
+  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));
+    }
 
   if (ggc_protect_identifiers)
     ggc_mark_stringpool ();
@@ -112,17 +180,16 @@ 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 ();
+
+  /* Some plugins may call ggc_set_mark from here.  */
+  invoke_plugin_callbacks (PLUGIN_GGC_MARKING, NULL);
 }
 
 /* Allocate a block of memory, then clear it.  */
@@ -435,6 +502,7 @@ gt_pch_save (FILE *f)
 
   gt_pch_save_stringpool ();
 
+  timevar_push (TV_PCH_PTR_REALLOC);
   saving_htab = htab_create (50000, saving_htab_hash, saving_htab_eq, free);
 
   for (rt = gt_ggc_rtab; *rt; rt++)
@@ -457,17 +525,22 @@ gt_pch_save (FILE *f)
 
   /* Try to arrange things so that no relocation is necessary, but
      don't try very hard.  On most platforms, this will always work,
-     and on the rest it's a lot of work to do better.  
+     and on the rest it's a lot of work to do better.
      (The extra work goes in HOST_HOOKS_GT_PCH_GET_ADDRESS and
      HOST_HOOKS_GT_PCH_USE_ADDRESS.)  */
   mmi.preferred_base = host_hooks.gt_pch_get_address (mmi.size, fileno (f));
-      
+
   ggc_pch_this_base (state.d, mmi.preferred_base);
 
   state.ptrs = XNEWVEC (struct ptr_data *, state.count);
   state.ptrs_i = 0;
+
   htab_traverse (saving_htab, call_alloc, &state);
+  timevar_pop (TV_PCH_PTR_REALLOC);
+
+  timevar_push (TV_PCH_PTR_SORT);
   qsort (state.ptrs, state.count, sizeof (*state.ptrs), compare_ptr_data);
+  timevar_pop (TV_PCH_PTR_SORT);
 
   /* Write out all the scalar variables.  */
   for (rt = gt_pch_scalar_rtab; *rt; rt++)
@@ -644,7 +717,7 @@ mmap_gt_pch_get_address (size_t size, int fd)
 }
 
 /* Default version of HOST_HOOKS_GT_PCH_USE_ADDRESS when mmap is present.
-   Map SIZE bytes of FD+OFFSET at BASE.  Return 1 if we succeeded at 
+   Map SIZE bytes of FD+OFFSET at BASE.  Return 1 if we succeeded at
    mapping the data at BASE, -1 if we couldn't.
 
    This version assumes that the kernel honors the START operand of mmap
@@ -736,7 +809,7 @@ ggc_min_heapsize_heuristic (void)
   phys_kbytes /= 8;
 
 #if defined(HAVE_GETRLIMIT) && defined (RLIMIT_RSS)
-  /* Try not to overrun the RSS limit while doing garbage collection.  
+  /* Try not to overrun the RSS limit while doing garbage collection.
      The RSS limit is only advisory, so no margin is subtracted.  */
  {
    struct rlimit rlim;
@@ -845,7 +918,7 @@ loc_descriptor (const char *name, int line, const char *function)
   if (!loc_hash)
     loc_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
 
-  slot = (struct loc_descriptor **) htab_find_slot (loc_hash, &loc, 1);
+  slot = (struct loc_descriptor **) htab_find_slot (loc_hash, &loc, INSERT);
   if (*slot)
     return *slot;
   *slot = XCNEW (struct loc_descriptor);