/* Simple garbage collection for the GNU compiler.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+ 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, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, 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. */
gt_handle_reorder reorder_fn;
size_t size;
void *new_addr;
+ enum gt_types_enum type;
};
#define POINTER_HASH(x) (hashval_t)((long)x >> 3)
int
gt_pch_note_object (void *obj, void *note_ptr_cookie,
- gt_note_pointers note_ptr_fn)
+ gt_note_pointers note_ptr_fn,
+ enum gt_types_enum type)
{
struct ptr_data **slot;
(*slot)->size = strlen (obj) + 1;
else
(*slot)->size = ggc_get_size (obj);
+ (*slot)->type = type;
return 1;
}
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. */
struct ptr_data *d = (struct ptr_data *)*slot;
struct traversal_state *state = (struct traversal_state *)state_p;
- ggc_pch_count_object (state->d, d->obj, d->size, d->note_ptr_fn == gt_pch_p_S);
+ ggc_pch_count_object (state->d, d->obj, d->size,
+ d->note_ptr_fn == gt_pch_p_S,
+ d->type);
state->count++;
return 1;
}
struct ptr_data *d = (struct ptr_data *)*slot;
struct traversal_state *state = (struct traversal_state *)state_p;
- d->new_addr = ggc_pch_alloc_object (state->d, d->obj, d->size, d->note_ptr_fn == gt_pch_p_S);
+ d->new_addr = ggc_pch_alloc_object (state->d, d->obj, d->size,
+ d->note_ptr_fn == gt_pch_p_S,
+ d->type);
state->ptrs[state->ptrs_i++] = d;
return 1;
}
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));
}
ggc_pch_this_base (state.d, mmi.preferred_base);
- state.ptrs = xmalloc (state.count * sizeof (*state.ptrs));
+ state.ptrs = XNEWVEC (struct ptr_data *, state.count);
state.ptrs_i = 0;
htab_traverse (saving_htab, call_alloc, &state);
qsort (state.ptrs, state.count, sizeof (*state.ptrs), compare_ptr_data);
write_pch_globals (gt_ggc_rtab, &state);
write_pch_globals (gt_pch_cache_rtab, &state);
- ggc_pch_prepare_write (state.d, state.f);
-
/* Pad the PCH file so that the mmapped area starts on an allocation
granularity (usually page) boundary. */
{
&& fseek (state.f, mmi.offset, SEEK_SET) != 0)
fatal_error ("can't write padding to PCH file: %m");
+ ggc_pch_prepare_write (state.d, state.f);
+
/* Actually write out the objects. */
for (i = 0; i < state.count; i++)
{
# 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);
}
const char *name, int line, const char *function)
{
struct loc_descriptor *loc = loc_descriptor (name, line, function);
- struct ptr_hash_entry *p = xmalloc (sizeof (struct ptr_hash_entry));
+ struct ptr_hash_entry *p = XNEW (struct ptr_hash_entry);
PTR *slot;
p->ptr = ptr;
}
/* 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];