/* Simple garbage collection for the GNU compiler.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* Generic garbage collection (GC) functions and data, not specific to
any particular GC implementation. */
# define MAP_FAILED ((void *)-1)
#endif
-#ifdef ENABLE_VALGRIND_CHECKING
-# ifdef HAVE_VALGRIND_MEMCHECK_H
-# include <valgrind/memcheck.h>
-# elif defined HAVE_MEMCHECK_H
-# include <memcheck.h>
-# else
-# include <valgrind.h>
-# endif
-#else
-/* Avoid #ifdef:s when we can help it. */
-#define VALGRIND_DISCARD(x)
-#endif
-
/* When set, ggc_collect will do collection. */
bool ggc_force_collect;
old_size as reachable, but that would lose tracking of writes
after the end of the object (by small offsets). Discard the
handle to avoid handle leak. */
- VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS ((char *) x + size,
- old_size - size));
- VALGRIND_DISCARD (VALGRIND_MAKE_READABLE (x, size));
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *) x + size,
+ old_size - size));
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (x, size));
return x;
}
individually allocated object, we'd access parts of the old object
that were marked invalid with the memcpy below. We lose a bit of the
initialization-tracking since some of it may be uninitialized. */
- VALGRIND_DISCARD (VALGRIND_MAKE_READABLE (x, old_size));
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (x, old_size));
memcpy (r, x, old_size);
static hashval_t
saving_htab_hash (const void *p)
{
- return POINTER_HASH (((struct ptr_data *)p)->obj);
+ return POINTER_HASH (((const struct ptr_data *)p)->obj);
}
static int
saving_htab_eq (const void *p1, const void *p2)
{
- return ((struct ptr_data *)p1)->obj == p2;
+ return ((const struct ptr_data *)p1)->obj == p2;
}
/* Handy state for the traversal functions. */
static int
compare_ptr_data (const void *p1_p, const void *p2_p)
{
- struct ptr_data *p1 = *(struct ptr_data *const *)p1_p;
- struct ptr_data *p2 = *(struct ptr_data *const *)p2_p;
+ const struct ptr_data *const p1 = *(const struct ptr_data *const *)p1_p;
+ const struct ptr_data *const p2 = *(const struct ptr_data *const *)p2_p;
return (((size_t)p1->new_addr > (size_t)p2->new_addr)
- ((size_t)p1->new_addr < (size_t)p2->new_addr));
}
# endif
/* Don't blindly run over our data limit; do GC at least when the
- *next* GC would be within 16Mb of the limit. If GCC does hit the
- data limit, compilation will fail, so this tries to be
- conservative. */
- limit_kbytes = MAX (0, limit_kbytes - 16 * 1024);
+ *next* GC would be within 20Mb of the limit or within a quarter of
+ the limit, whichever is larger. If GCC does hit the data limit,
+ compilation will fail, so this tries to be conservative. */
+ limit_kbytes = MAX (0, limit_kbytes - MAX (limit_kbytes / 4, 20 * 1024));
limit_kbytes = (limit_kbytes * 100) / (110 + ggc_min_expand_heuristic());
phys_kbytes = MIN (phys_kbytes, limit_kbytes);
static hashval_t
hash_descriptor (const void *p)
{
- const struct loc_descriptor *d = p;
+ const struct loc_descriptor *const d = p;
return htab_hash_pointer (d->function) | d->line;
}
static int
eq_descriptor (const void *p1, const void *p2)
{
- const struct loc_descriptor *d = p1;
- const struct loc_descriptor *d2 = p2;
+ const struct loc_descriptor *const d = p1;
+ const struct loc_descriptor *const d2 = p2;
return (d->file == d2->file && d->line == d2->line
&& d->function == d2->function);
static hashval_t
hash_ptr (const void *p)
{
- const struct ptr_hash_entry *d = p;
+ const struct ptr_hash_entry *const d = p;
return htab_hash_pointer (d->ptr);
}
static int
eq_ptr (const void *p1, const void *p2)
{
- const struct ptr_hash_entry *p = p1;
+ const struct ptr_hash_entry *const p = p1;
return (p->ptr == p2);
}
}
/* Notice that the pointer has been freed. */
-void ggc_free_overhead (void *ptr)
+void
+ggc_free_overhead (void *ptr)
{
PTR *slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer (ptr),
NO_INSERT);
/* Helper for qsort; sort descriptors by amount of memory consumed. */
static int
-cmp_statistic (const void *loc1, const void *loc2)
+final_cmp_statistic (const void *loc1, const void *loc2)
{
struct loc_descriptor *l1 = *(struct loc_descriptor **) loc1;
struct loc_descriptor *l2 = *(struct loc_descriptor **) loc2;
- return ((l1->allocated + l1->overhead - l1->freed) -
+ long diff;
+ diff = ((long)(l1->allocated + l1->overhead - l1->freed) -
(l2->allocated + l2->overhead - l2->freed));
+ return diff > 0 ? 1 : diff < 0 ? -1 : 0;
+}
+
+/* Helper for qsort; sort descriptors by amount of memory consumed. */
+static int
+cmp_statistic (const void *loc1, const void *loc2)
+{
+ struct loc_descriptor *l1 = *(struct loc_descriptor **) loc1;
+ struct loc_descriptor *l2 = *(struct loc_descriptor **) loc2;
+ long diff;
+
+ diff = ((long)(l1->allocated + l1->overhead - l1->freed - l1->collected) -
+ (l2->allocated + l2->overhead - l2->freed - l2->collected));
+ if (diff)
+ return diff > 0 ? 1 : diff < 0 ? -1 : 0;
+ diff = ((long)(l1->allocated + l1->overhead - l1->freed) -
+ (l2->allocated + l2->overhead - l2->freed));
+ return diff > 0 ? 1 : diff < 0 ? -1 : 0;
}
/* Collect array of the descriptors from hashtable. */
/* Dump per-site memory statistics. */
#endif
-void dump_ggc_loc_statistics (void)
+void
+dump_ggc_loc_statistics (bool final ATTRIBUTE_UNUSED)
{
#ifdef GATHER_STATISTICS
int nentries = 0;
"source location", "Garbage", "Freed", "Leak", "Overhead", "Times");
fprintf (stderr, "-------------------------------------------------------\n");
htab_traverse (loc_hash, add_statistics, &nentries);
- qsort (loc_array, nentries, sizeof (*loc_array), cmp_statistic);
+ qsort (loc_array, nentries, sizeof (*loc_array),
+ final ? final_cmp_statistic : cmp_statistic);
for (i = 0; i < nentries; i++)
{
struct loc_descriptor *d = loc_array[i];
fprintf (stderr, "%-48s %10s %10s %10s %10s %10s\n",
"source location", "Garbage", "Freed", "Leak", "Overhead", "Times");
fprintf (stderr, "-------------------------------------------------------\n");
+ ggc_force_collect = false;
#endif
}