MAINTAINERS (Write After Approval): Add myself.
[platform/upstream/gcc.git] / gcc / ggc-page.c
index 2236a3a..2b42b6e 100644 (file)
@@ -1,5 +1,5 @@
 /* "Bag-of-pages" garbage collector for the GNU compiler.
-   Copyright (C) 1999-2014 Free Software Foundation, Inc.
+   Copyright (C) 1999-2016 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -20,13 +20,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
+#include "alias.h"
 #include "tree.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "diagnostic-core.h"
 #include "flags.h"
-#include "ggc.h"
 #include "ggc-internal.h"
 #include "timevar.h"
 #include "params.h"
@@ -216,13 +216,9 @@ static const size_t extra_order_size_table[] = {
 
 #define ROUND_UP_VALUE(x, f) ((f) - 1 - ((f) - 1 + (x)) % (f))
 
-/* Compute the smallest multiple of F that is >= X.  */
-
-#define ROUND_UP(x, f) (CEIL (x, f) * (f))
-
 /* Round X to next multiple of the page size */
 
-#define PAGE_ALIGN(x) (((x) + G.pagesize - 1) & ~(G.pagesize - 1))
+#define PAGE_ALIGN(x) ROUND_UP ((x), G.pagesize)
 
 /* The Ith entry is the number of objects on a page or order I.  */
 
@@ -245,7 +241,7 @@ inverse_table[NUM_ORDERS];
 
 /* A page_entry records the status of an allocation page.  This
    structure is dynamically sized to fit the bitmap in_use_p.  */
-typedef struct page_entry
+struct page_entry
 {
   /* The next page-entry with objects of the same size, or NULL if
      this is the last page-entry.  */
@@ -292,12 +288,12 @@ typedef struct page_entry
      Nth bit is one if the Nth object on this page is allocated.  This
      array is dynamically sized.  */
   unsigned long in_use_p[1];
-} page_entry;
+};
 
 #ifdef USING_MALLOC_PAGE_GROUPS
 /* A page_group describes a large allocation from malloc, from which
    we parcel out aligned pages.  */
-typedef struct page_group
+struct page_group
 {
   /* A linked list of all extant page groups.  */
   struct page_group *next;
@@ -310,7 +306,7 @@ typedef struct page_group
 
   /* A bitmask of pages in use.  */
   unsigned int in_use;
-} page_group;
+};
 #endif
 
 #if HOST_BITS_PER_PTR <= 32
@@ -365,7 +361,7 @@ private:
   void (*m_function)(void *);
   size_t m_object_size;
   size_t m_n_objects;
-  };
+};
 
 #ifdef ENABLE_GC_ALWAYS_COLLECT
 /* List of free objects to be verified as actually free on the
@@ -460,11 +456,11 @@ static struct ggc_globals
      better runtime data access pattern.  */
   unsigned long **save_in_use;
 
-  /* Finalizers for single objects.  */
-  vec<finalizer> finalizers;
+  /* Finalizers for single objects.  The first index is collection_depth.  */
+  vec<vec<finalizer> > finalizers;
 
   /* Finalizers for vectors of objects.  */
-  vec<vec_finalizer> vec_finalizers;
+  vec<vec<vec_finalizer> > vec_finalizers;
 
 #ifdef ENABLE_GC_ALWAYS_COLLECT
   /* List of free objects to be verified as actually free on the
@@ -1244,6 +1240,25 @@ ggc_round_alloc_size (size_t requested_size)
   return size;
 }
 
+/* Push a finalizer onto the appropriate vec.  */
+
+static void
+add_finalizer (void *result, void (*f)(void *), size_t s, size_t n)
+{
+  if (f == NULL)
+    /* No finalizer.  */;
+  else if (n == 1)
+    {
+      finalizer fin (result, f);
+      G.finalizers[G.context_depth].safe_push (fin);
+    }
+  else
+    {
+      vec_finalizer fin (reinterpret_cast<uintptr_t> (result), f, s, n);
+      G.vec_finalizers[G.context_depth].safe_push (fin);
+    }
+}
+
 /* Allocate a chunk of memory of SIZE bytes.  Its contents are undefined.  */
 
 void *
@@ -1391,11 +1406,8 @@ ggc_internal_alloc (size_t size, void (*f)(void *), size_t s, size_t n
   /* For timevar statistics.  */
   timevar_ggc_mem_total += object_size;
 
-  if (f && n == 1)
-    G.finalizers.safe_push (finalizer (result, f));
-  else if (f)
-    G.vec_finalizers.safe_push
-      (vec_finalizer (reinterpret_cast<uintptr_t> (result), f, s, n));
+  if (f)
+    add_finalizer (result, f, s, n);
 
   if (GATHER_STATISTICS)
     {
@@ -1792,6 +1804,11 @@ init_ggc (void)
   G.by_depth_max = INITIAL_PTE_COUNT;
   G.by_depth = XNEWVEC (page_entry *, G.by_depth_max);
   G.save_in_use = XNEWVEC (unsigned long *, G.by_depth_max);
+
+  /* Allocate space for the depth 0 finalizers.  */
+  G.finalizers.safe_push (vNULL);
+  G.vec_finalizers.safe_push (vNULL);
+  gcc_assert (G.finalizers.length() == 1);
 }
 
 /* Merge the SAVE_IN_USE_P and IN_USE_P arrays in P so that IN_USE_P
@@ -1879,36 +1896,42 @@ clear_marks (void)
 static void
 ggc_handle_finalizers ()
 {
-  if (G.context_depth != 0)
-    return;
-
-  unsigned length = G.finalizers.length ();
-  for (unsigned int i = 0; i < length;)
+  unsigned dlen = G.finalizers.length();
+  for (unsigned d = G.context_depth; d < dlen; ++d)
     {
-      finalizer &f = G.finalizers[i];
-      if (!ggc_marked_p (f.addr ()))
+      vec<finalizer> &v = G.finalizers[d];
+      unsigned length = v.length ();
+      for (unsigned int i = 0; i < length;)
        {
-         f.call ();
-         G.finalizers.unordered_remove (i);
-         length--;
+         finalizer &f = v[i];
+         if (!ggc_marked_p (f.addr ()))
+           {
+             f.call ();
+             v.unordered_remove (i);
+             length--;
+           }
+         else
+           i++;
        }
-      else
-       i++;
     }
 
-
-  length = G.vec_finalizers.length ();
-  for (unsigned int i = 0; i < length;)
+  gcc_assert (dlen == G.vec_finalizers.length());
+  for (unsigned d = G.context_depth; d < dlen; ++d)
     {
-      vec_finalizer &f = G.vec_finalizers[i];
-      if (!ggc_marked_p (f.addr ()))
+      vec<vec_finalizer> &vv = G.vec_finalizers[d];
+      unsigned length = vv.length ();
+      for (unsigned int i = 0; i < length;)
        {
-         f.call ();
-         G.vec_finalizers.unordered_remove (i);
-         length--;
+         vec_finalizer &f = vv[i];
+         if (!ggc_marked_p (f.addr ()))
+           {
+             f.call ();
+             vv.unordered_remove (i);
+             length--;
+           }
+         else
+           i++;
        }
-      else
-       i++;
     }
 }
 
@@ -2205,12 +2228,11 @@ ggc_collect (void)
 void
 ggc_grow (void)
 {
-#ifndef ENABLE_CHECKING
-  G.allocated_last_gc = MAX (G.allocated_last_gc,
-                            G.allocated);
-#else
-  ggc_collect ();
-#endif
+  if (!flag_checking)
+    G.allocated_last_gc = MAX (G.allocated_last_gc,
+                              G.allocated);
+  else
+    ggc_collect ();
   if (!quiet_flag)
     fprintf (stderr, " {GC start %luk} ", (unsigned long) G.allocated / 1024);
 }
@@ -2247,7 +2269,7 @@ ggc_print_statistics (void)
      allocation.  */
   fprintf (stderr,
            "Memory still allocated at the end of the compilation process\n");
-  fprintf (stderr, "%-5s %10s  %10s  %10s\n",
+  fprintf (stderr, "%-8s %10s  %10s  %10s\n",
           "Size", "Allocated", "Used", "Overhead");
   for (i = 0; i < NUM_ORDERS; ++i)
     {
@@ -2274,47 +2296,51 @@ ggc_print_statistics (void)
          overhead += (sizeof (page_entry) - sizeof (long)
                       + BITMAP_SIZE (OBJECTS_IN_PAGE (p) + 1));
        }
-      fprintf (stderr, "%-5lu %10lu%c %10lu%c %10lu%c\n",
+      fprintf (stderr, "%-8lu %10lu%c %10lu%c %10lu%c\n",
               (unsigned long) OBJECT_SIZE (i),
               SCALE (allocated), STAT_LABEL (allocated),
               SCALE (in_use), STAT_LABEL (in_use),
               SCALE (overhead), STAT_LABEL (overhead));
       total_overhead += overhead;
     }
-  fprintf (stderr, "%-5s %10lu%c %10lu%c %10lu%c\n", "Total",
+  fprintf (stderr, "%-8s %10lu%c %10lu%c %10lu%c\n", "Total",
           SCALE (G.bytes_mapped), STAT_LABEL (G.bytes_mapped),
           SCALE (G.allocated), STAT_LABEL (G.allocated),
           SCALE (total_overhead), STAT_LABEL (total_overhead));
 
   if (GATHER_STATISTICS)
     {
-      fprintf (stderr, "\nTotal allocations and overheads during the compilation process\n");
+      fprintf (stderr, "\nTotal allocations and overheads during "
+              "the compilation process\n");
 
-      fprintf (stderr, "Total Overhead:                        %10" HOST_LONG_LONG_FORMAT "d\n",
-              G.stats.total_overhead);
-      fprintf (stderr, "Total Allocated:                       %10" HOST_LONG_LONG_FORMAT "d\n",
+      fprintf (stderr, "Total Overhead:                          %10"
+              HOST_LONG_LONG_FORMAT "d\n", G.stats.total_overhead);
+      fprintf (stderr, "Total Allocated:                         %10"
+              HOST_LONG_LONG_FORMAT "d\n",
               G.stats.total_allocated);
 
-      fprintf (stderr, "Total Overhead  under  32B:            %10" HOST_LONG_LONG_FORMAT "d\n",
-              G.stats.total_overhead_under32);
-      fprintf (stderr, "Total Allocated under  32B:            %10" HOST_LONG_LONG_FORMAT "d\n",
-              G.stats.total_allocated_under32);
-      fprintf (stderr, "Total Overhead  under  64B:            %10" HOST_LONG_LONG_FORMAT "d\n",
-              G.stats.total_overhead_under64);
-      fprintf (stderr, "Total Allocated under  64B:            %10" HOST_LONG_LONG_FORMAT "d\n",
-              G.stats.total_allocated_under64);
-      fprintf (stderr, "Total Overhead  under 128B:            %10" HOST_LONG_LONG_FORMAT "d\n",
-              G.stats.total_overhead_under128);
-      fprintf (stderr, "Total Allocated under 128B:            %10" HOST_LONG_LONG_FORMAT "d\n",
-              G.stats.total_allocated_under128);
+      fprintf (stderr, "Total Overhead  under  32B:              %10"
+              HOST_LONG_LONG_FORMAT "d\n", G.stats.total_overhead_under32);
+      fprintf (stderr, "Total Allocated under  32B:              %10"
+              HOST_LONG_LONG_FORMAT "d\n", G.stats.total_allocated_under32);
+      fprintf (stderr, "Total Overhead  under  64B:              %10"
+              HOST_LONG_LONG_FORMAT "d\n", G.stats.total_overhead_under64);
+      fprintf (stderr, "Total Allocated under  64B:              %10"
+              HOST_LONG_LONG_FORMAT "d\n", G.stats.total_allocated_under64);
+      fprintf (stderr, "Total Overhead  under 128B:              %10"
+              HOST_LONG_LONG_FORMAT "d\n", G.stats.total_overhead_under128);
+      fprintf (stderr, "Total Allocated under 128B:              %10"
+              HOST_LONG_LONG_FORMAT "d\n", G.stats.total_allocated_under128);
 
       for (i = 0; i < NUM_ORDERS; i++)
        if (G.stats.total_allocated_per_order[i])
          {
-           fprintf (stderr, "Total Overhead  page size %7lu:     %10" HOST_LONG_LONG_FORMAT "d\n",
+           fprintf (stderr, "Total Overhead  page size %9lu:     %10"
+                    HOST_LONG_LONG_FORMAT "d\n",
                     (unsigned long) OBJECT_SIZE (i),
                     G.stats.total_overhead_per_order[i]);
-           fprintf (stderr, "Total Allocated page size %7lu:     %10" HOST_LONG_LONG_FORMAT "d\n",
+           fprintf (stderr, "Total Allocated page size %9lu:     %10"
+                    HOST_LONG_LONG_FORMAT "d\n",
                     (unsigned long) OBJECT_SIZE (i),
                     G.stats.total_allocated_per_order[i]);
          }
@@ -2428,7 +2454,7 @@ ggc_pch_write_object (struct ggc_pch_data *d,
     }
 
   if (fwrite (x, size, 1, f) != 1)
-    fatal_error ("can%'t write PCH file: %m");
+    fatal_error (input_location, "can%'t write PCH file: %m");
 
   /* If SIZE is not the same as OBJECT_SIZE(order), then we need to pad the
      object out to OBJECT_SIZE(order).  This happens for strings.  */
@@ -2444,13 +2470,13 @@ ggc_pch_write_object (struct ggc_pch_data *d,
       if (padding <= sizeof (emptyBytes))
         {
           if (fwrite (emptyBytes, 1, padding, f) != padding)
-            fatal_error ("can%'t write PCH file");
+            fatal_error (input_location, "can%'t write PCH file");
         }
       else
         {
           /* Larger than our buffer?  Just default to fseek.  */
           if (fseek (f, padding, SEEK_CUR) != 0)
-            fatal_error ("can%'t write PCH file");
+            fatal_error (input_location, "can%'t write PCH file");
         }
     }
 
@@ -2459,14 +2485,14 @@ ggc_pch_write_object (struct ggc_pch_data *d,
       && fseek (f, ROUND_UP_VALUE (d->d.totals[order] * OBJECT_SIZE (order),
                                   G.pagesize),
                SEEK_CUR) != 0)
-    fatal_error ("can%'t write PCH file: %m");
+    fatal_error (input_location, "can%'t write PCH file: %m");
 }
 
 void
 ggc_pch_finish (struct ggc_pch_data *d, FILE *f)
 {
   if (fwrite (&d->d, sizeof (d->d), 1, f) != 1)
-    fatal_error ("can%'t write PCH file: %m");
+    fatal_error (input_location, "can%'t write PCH file: %m");
   free (d);
 }
 
@@ -2546,6 +2572,10 @@ ggc_pch_read (FILE *f, void *addr)
      pages to be 1 too.  PCH pages will have depth 0.  */
   gcc_assert (!G.context_depth);
   G.context_depth = 1;
+  /* Allocate space for the depth 1 finalizers.  */
+  G.finalizers.safe_push (vNULL);
+  G.vec_finalizers.safe_push (vNULL);
+  gcc_assert (G.finalizers.length() == 2);
   for (i = 0; i < NUM_ORDERS; i++)
     {
       page_entry *p;
@@ -2556,7 +2586,7 @@ ggc_pch_read (FILE *f, void *addr)
   /* Allocate the appropriate page-table entries for the pages read from
      the PCH file.  */
   if (fread (&d, sizeof (d), 1, f) != 1)
-    fatal_error ("can%'t read PCH file: %m");
+    fatal_error (input_location, "can%'t read PCH file: %m");
 
   for (i = 0; i < NUM_ORDERS; i++)
     {