/* "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.
#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"
#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. */
/* 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. */
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;
/* A bitmask of pages in use. */
unsigned int in_use;
-} page_group;
+};
#endif
#if HOST_BITS_PER_PTR <= 32
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
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
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 *
/* 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)
{
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
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++;
}
}
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);
}
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)
{
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]);
}
}
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. */
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");
}
}
&& 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);
}
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;
/* 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++)
{