comparison gcc/ggc-common.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
comparison
equal deleted inserted replaced
68:561a7518be6b 111:04ced10e8804
1 /* Simple garbage collection for the GNU compiler. 1 /* Simple garbage collection for the GNU compiler.
2 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2 Copyright (C) 1999-2017 Free Software Foundation, Inc.
3 2009, 2010 Free Software Foundation, Inc.
4 3
5 This file is part of GCC. 4 This file is part of GCC.
6 5
7 GCC is free software; you can redistribute it and/or modify it under 6 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free 7 the terms of the GNU General Public License as published by the Free
22 any particular GC implementation. */ 21 any particular GC implementation. */
23 22
24 #include "config.h" 23 #include "config.h"
25 #include "system.h" 24 #include "system.h"
26 #include "coretypes.h" 25 #include "coretypes.h"
27 #include "hashtab.h" 26 #include "timevar.h"
28 #include "ggc.h" 27 #include "diagnostic-core.h"
29 #include "ggc-internal.h" 28 #include "ggc-internal.h"
30 #include "diagnostic-core.h"
31 #include "params.h" 29 #include "params.h"
32 #include "hosthooks.h" 30 #include "hosthooks.h"
33 #include "hosthooks-def.h"
34 #include "plugin.h" 31 #include "plugin.h"
35 #include "vec.h"
36 #include "timevar.h"
37 32
38 /* When set, ggc_collect will do collection. */ 33 /* When set, ggc_collect will do collection. */
39 bool ggc_force_collect; 34 bool ggc_force_collect;
40 35
41 /* When true, protect the contents of the identifier hash table. */ 36 /* When true, protect the contents of the identifier hash table. */
44 /* Statistics about the allocation. */ 39 /* Statistics about the allocation. */
45 static ggc_statistics *ggc_stats; 40 static ggc_statistics *ggc_stats;
46 41
47 struct traversal_state; 42 struct traversal_state;
48 43
49 static int ggc_htab_delete (void **, void *);
50 static hashval_t saving_htab_hash (const void *);
51 static int saving_htab_eq (const void *, const void *);
52 static int call_count (void **, void *);
53 static int call_alloc (void **, void *);
54 static int compare_ptr_data (const void *, const void *); 44 static int compare_ptr_data (const void *, const void *);
55 static void relocate_ptrs (void *, void *); 45 static void relocate_ptrs (void *, void *);
56 static void write_pch_globals (const struct ggc_root_tab * const *tab, 46 static void write_pch_globals (const struct ggc_root_tab * const *tab,
57 struct traversal_state *state); 47 struct traversal_state *state);
58 48
59 /* Maintain global roots that are preserved during GC. */ 49 /* Maintain global roots that are preserved during GC. */
60
61 /* Process a slot of an htab by deleting it if it has not been marked. */
62
63 static int
64 ggc_htab_delete (void **slot, void *info)
65 {
66 const struct ggc_cache_tab *r = (const struct ggc_cache_tab *) info;
67
68 if (! (*r->marked_p) (*slot))
69 htab_clear_slot (*r->base, slot);
70 else
71 (*r->cb) (*slot);
72
73 return 1;
74 }
75
76 50
77 /* This extra vector of dynamically registered root_tab-s is used by 51 /* This extra vector of dynamically registered root_tab-s is used by
78 ggc_mark_roots and gives the ability to dynamically add new GGC root 52 ggc_mark_roots and gives the ability to dynamically add new GGC root
79 tables, for instance from some plugins; this vector is on the heap 53 tables, for instance from some plugins; this vector is on the heap
80 since it is used by GGC internally. */ 54 since it is used by GGC internally. */
81 typedef const struct ggc_root_tab *const_ggc_root_tab_t; 55 typedef const struct ggc_root_tab *const_ggc_root_tab_t;
82 DEF_VEC_P(const_ggc_root_tab_t); 56 static vec<const_ggc_root_tab_t> extra_root_vec;
83 DEF_VEC_ALLOC_P(const_ggc_root_tab_t, heap);
84 static VEC(const_ggc_root_tab_t, heap) *extra_root_vec;
85 57
86 /* Dynamically register a new GGC root table RT. This is useful for 58 /* Dynamically register a new GGC root table RT. This is useful for
87 plugins. */ 59 plugins. */
88 60
89 void 61 void
90 ggc_register_root_tab (const struct ggc_root_tab* rt) 62 ggc_register_root_tab (const struct ggc_root_tab* rt)
91 { 63 {
92 if (rt) 64 if (rt)
93 VEC_safe_push (const_ggc_root_tab_t, heap, extra_root_vec, rt); 65 extra_root_vec.safe_push (rt);
94 }
95
96 /* This extra vector of dynamically registered cache_tab-s is used by
97 ggc_mark_roots and gives the ability to dynamically add new GGC cache
98 tables, for instance from some plugins; this vector is on the heap
99 since it is used by GGC internally. */
100 typedef const struct ggc_cache_tab *const_ggc_cache_tab_t;
101 DEF_VEC_P(const_ggc_cache_tab_t);
102 DEF_VEC_ALLOC_P(const_ggc_cache_tab_t, heap);
103 static VEC(const_ggc_cache_tab_t, heap) *extra_cache_vec;
104
105 /* Dynamically register a new GGC cache table CT. This is useful for
106 plugins. */
107
108 void
109 ggc_register_cache_tab (const struct ggc_cache_tab* ct)
110 {
111 if (ct)
112 VEC_safe_push (const_ggc_cache_tab_t, heap, extra_cache_vec, ct);
113 }
114
115 /* Scan a hash table that has objects which are to be deleted if they are not
116 already marked. */
117
118 static void
119 ggc_scan_cache_tab (const_ggc_cache_tab_t ctp)
120 {
121 const struct ggc_cache_tab *cti;
122
123 for (cti = ctp; cti->base != NULL; cti++)
124 if (*cti->base)
125 {
126 ggc_set_mark (*cti->base);
127 htab_traverse_noresize (*cti->base, ggc_htab_delete,
128 CONST_CAST (void *, (const void *)cti));
129 ggc_set_mark ((*cti->base)->entries);
130 }
131 } 66 }
132 67
133 /* Mark all the roots in the table RT. */ 68 /* Mark all the roots in the table RT. */
134 69
135 static void 70 static void
147 void 82 void
148 ggc_mark_roots (void) 83 ggc_mark_roots (void)
149 { 84 {
150 const struct ggc_root_tab *const *rt; 85 const struct ggc_root_tab *const *rt;
151 const_ggc_root_tab_t rtp, rti; 86 const_ggc_root_tab_t rtp, rti;
152 const struct ggc_cache_tab *const *ct;
153 const_ggc_cache_tab_t ctp;
154 size_t i; 87 size_t i;
155 88
156 for (rt = gt_ggc_deletable_rtab; *rt; rt++) 89 for (rt = gt_ggc_deletable_rtab; *rt; rt++)
157 for (rti = *rt; rti->base != NULL; rti++) 90 for (rti = *rt; rti->base != NULL; rti++)
158 memset (rti->base, 0, rti->stride); 91 memset (rti->base, 0, rti->stride);
159 92
160 for (rt = gt_ggc_rtab; *rt; rt++) 93 for (rt = gt_ggc_rtab; *rt; rt++)
161 ggc_mark_root_tab (*rt); 94 ggc_mark_root_tab (*rt);
162 95
163 FOR_EACH_VEC_ELT (const_ggc_root_tab_t, extra_root_vec, i, rtp) 96 FOR_EACH_VEC_ELT (extra_root_vec, i, rtp)
164 ggc_mark_root_tab (rtp); 97 ggc_mark_root_tab (rtp);
165 98
166 if (ggc_protect_identifiers) 99 if (ggc_protect_identifiers)
167 ggc_mark_stringpool (); 100 ggc_mark_stringpool ();
168 101
169 /* Now scan all hash tables that have objects which are to be deleted if 102 gt_clear_caches ();
170 they are not already marked. */
171 for (ct = gt_ggc_cache_rtab; *ct; ct++)
172 ggc_scan_cache_tab (*ct);
173
174 FOR_EACH_VEC_ELT (const_ggc_cache_tab_t, extra_cache_vec, i, ctp)
175 ggc_scan_cache_tab (ctp);
176 103
177 if (! ggc_protect_identifiers) 104 if (! ggc_protect_identifiers)
178 ggc_purge_stringpool (); 105 ggc_purge_stringpool ();
179 106
180 /* Some plugins may call ggc_set_mark from here. */ 107 /* Some plugins may call ggc_set_mark from here. */
181 invoke_plugin_callbacks (PLUGIN_GGC_MARKING, NULL); 108 invoke_plugin_callbacks (PLUGIN_GGC_MARKING, NULL);
182 } 109 }
183 110
184 /* Allocate a block of memory, then clear it. */ 111 /* Allocate a block of memory, then clear it. */
185 void * 112 void *
186 ggc_internal_cleared_alloc_stat (size_t size MEM_STAT_DECL) 113 ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t s, size_t n
187 { 114 MEM_STAT_DECL)
188 void *buf = ggc_internal_alloc_stat (size PASS_MEM_STAT); 115 {
116 void *buf = ggc_internal_alloc (size, f, s, n PASS_MEM_STAT);
189 memset (buf, 0, size); 117 memset (buf, 0, size);
190 return buf; 118 return buf;
191 } 119 }
192 120
193 /* Resize a block of memory, possibly re-allocating it. */ 121 /* Resize a block of memory, possibly re-allocating it. */
194 void * 122 void *
195 ggc_realloc_stat (void *x, size_t size MEM_STAT_DECL) 123 ggc_realloc (void *x, size_t size MEM_STAT_DECL)
196 { 124 {
197 void *r; 125 void *r;
198 size_t old_size; 126 size_t old_size;
199 127
200 if (x == NULL) 128 if (x == NULL)
201 return ggc_internal_alloc_stat (size PASS_MEM_STAT); 129 return ggc_internal_alloc (size PASS_MEM_STAT);
202 130
203 old_size = ggc_get_size (x); 131 old_size = ggc_get_size (x);
204 132
205 if (size <= old_size) 133 if (size <= old_size)
206 { 134 {
218 old_size - size)); 146 old_size - size));
219 VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (x, size)); 147 VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (x, size));
220 return x; 148 return x;
221 } 149 }
222 150
223 r = ggc_internal_alloc_stat (size PASS_MEM_STAT); 151 r = ggc_internal_alloc (size PASS_MEM_STAT);
224 152
225 /* Since ggc_get_size returns the size of the pool, not the size of the 153 /* Since ggc_get_size returns the size of the pool, not the size of the
226 individually allocated object, we'd access parts of the old object 154 individually allocated object, we'd access parts of the old object
227 that were marked invalid with the memcpy below. We lose a bit of the 155 that were marked invalid with the memcpy below. We lose a bit of the
228 initialization-tracking since some of it may be uninitialized. */ 156 initialization-tracking since some of it may be uninitialized. */
239 void * 167 void *
240 ggc_cleared_alloc_htab_ignore_args (size_t c ATTRIBUTE_UNUSED, 168 ggc_cleared_alloc_htab_ignore_args (size_t c ATTRIBUTE_UNUSED,
241 size_t n ATTRIBUTE_UNUSED) 169 size_t n ATTRIBUTE_UNUSED)
242 { 170 {
243 gcc_assert (c * n == sizeof (struct htab)); 171 gcc_assert (c * n == sizeof (struct htab));
244 return ggc_alloc_cleared_htab (); 172 return ggc_cleared_alloc<htab> ();
245 } 173 }
246 174
247 /* TODO: once we actually use type information in GGC, create a new tag 175 /* TODO: once we actually use type information in GGC, create a new tag
248 gt_gcc_ptr_array and use it for pointer arrays. */ 176 gt_gcc_ptr_array and use it for pointer arrays. */
249 void * 177 void *
250 ggc_cleared_alloc_ptr_array_two_args (size_t c, size_t n) 178 ggc_cleared_alloc_ptr_array_two_args (size_t c, size_t n)
251 { 179 {
252 gcc_assert (sizeof (PTR *) == n); 180 gcc_assert (sizeof (PTR *) == n);
253 return ggc_internal_cleared_vec_alloc (sizeof (PTR *), c); 181 return ggc_cleared_vec_alloc<PTR *> (c);
254 } 182 }
255 183
256 /* These are for splay_tree_new_ggc. */ 184 /* These are for splay_tree_new_ggc. */
257 void * 185 void *
258 ggc_splay_alloc (enum gt_types_enum obj_type ATTRIBUTE_UNUSED, int sz, 186 ggc_splay_alloc (int sz, void *nl)
259 void *nl)
260 { 187 {
261 gcc_assert (!nl); 188 gcc_assert (!nl);
262 return ggc_internal_alloc (sz); 189 return ggc_internal_alloc (sz);
263 } 190 }
264 191
293 ggc_stats = NULL; 220 ggc_stats = NULL;
294 } 221 }
295 222
296 /* Functions for saving and restoring GCable memory to disk. */ 223 /* Functions for saving and restoring GCable memory to disk. */
297 224
298 static htab_t saving_htab;
299
300 struct ptr_data 225 struct ptr_data
301 { 226 {
302 void *obj; 227 void *obj;
303 void *note_ptr_cookie; 228 void *note_ptr_cookie;
304 gt_note_pointers note_ptr_fn; 229 gt_note_pointers note_ptr_fn;
305 gt_handle_reorder reorder_fn; 230 gt_handle_reorder reorder_fn;
306 size_t size; 231 size_t size;
307 void *new_addr; 232 void *new_addr;
308 enum gt_types_enum type;
309 }; 233 };
310 234
311 #define POINTER_HASH(x) (hashval_t)((long)x >> 3) 235 #define POINTER_HASH(x) (hashval_t)((intptr_t)x >> 3)
236
237 /* Helper for hashing saving_htab. */
238
239 struct saving_hasher : free_ptr_hash <ptr_data>
240 {
241 typedef void *compare_type;
242 static inline hashval_t hash (const ptr_data *);
243 static inline bool equal (const ptr_data *, const void *);
244 };
245
246 inline hashval_t
247 saving_hasher::hash (const ptr_data *p)
248 {
249 return POINTER_HASH (p->obj);
250 }
251
252 inline bool
253 saving_hasher::equal (const ptr_data *p1, const void *p2)
254 {
255 return p1->obj == p2;
256 }
257
258 static hash_table<saving_hasher> *saving_htab;
312 259
313 /* Register an object in the hash table. */ 260 /* Register an object in the hash table. */
314 261
315 int 262 int
316 gt_pch_note_object (void *obj, void *note_ptr_cookie, 263 gt_pch_note_object (void *obj, void *note_ptr_cookie,
317 gt_note_pointers note_ptr_fn, 264 gt_note_pointers note_ptr_fn)
318 enum gt_types_enum type)
319 { 265 {
320 struct ptr_data **slot; 266 struct ptr_data **slot;
321 267
322 if (obj == NULL || obj == (void *) 1) 268 if (obj == NULL || obj == (void *) 1)
323 return 0; 269 return 0;
324 270
325 slot = (struct ptr_data **) 271 slot = (struct ptr_data **)
326 htab_find_slot_with_hash (saving_htab, obj, POINTER_HASH (obj), 272 saving_htab->find_slot_with_hash (obj, POINTER_HASH (obj), INSERT);
327 INSERT);
328 if (*slot != NULL) 273 if (*slot != NULL)
329 { 274 {
330 gcc_assert ((*slot)->note_ptr_fn == note_ptr_fn 275 gcc_assert ((*slot)->note_ptr_fn == note_ptr_fn
331 && (*slot)->note_ptr_cookie == note_ptr_cookie); 276 && (*slot)->note_ptr_cookie == note_ptr_cookie);
332 return 0; 277 return 0;
338 (*slot)->note_ptr_cookie = note_ptr_cookie; 283 (*slot)->note_ptr_cookie = note_ptr_cookie;
339 if (note_ptr_fn == gt_pch_p_S) 284 if (note_ptr_fn == gt_pch_p_S)
340 (*slot)->size = strlen ((const char *)obj) + 1; 285 (*slot)->size = strlen ((const char *)obj) + 1;
341 else 286 else
342 (*slot)->size = ggc_get_size (obj); 287 (*slot)->size = ggc_get_size (obj);
343 (*slot)->type = type;
344 return 1; 288 return 1;
345 } 289 }
346 290
347 /* Register an object in the hash table. */ 291 /* Register an object in the hash table. */
348 292
354 298
355 if (obj == NULL || obj == (void *) 1) 299 if (obj == NULL || obj == (void *) 1)
356 return; 300 return;
357 301
358 data = (struct ptr_data *) 302 data = (struct ptr_data *)
359 htab_find_with_hash (saving_htab, obj, POINTER_HASH (obj)); 303 saving_htab->find_with_hash (obj, POINTER_HASH (obj));
360 gcc_assert (data && data->note_ptr_cookie == note_ptr_cookie); 304 gcc_assert (data && data->note_ptr_cookie == note_ptr_cookie);
361 305
362 data->reorder_fn = reorder_fn; 306 data->reorder_fn = reorder_fn;
363 }
364
365 /* Hash and equality functions for saving_htab, callbacks for htab_create. */
366
367 static hashval_t
368 saving_htab_hash (const void *p)
369 {
370 return POINTER_HASH (((const struct ptr_data *)p)->obj);
371 }
372
373 static int
374 saving_htab_eq (const void *p1, const void *p2)
375 {
376 return ((const struct ptr_data *)p1)->obj == p2;
377 } 307 }
378 308
379 /* Handy state for the traversal functions. */ 309 /* Handy state for the traversal functions. */
380 310
381 struct traversal_state 311 struct traversal_state
387 size_t ptrs_i; 317 size_t ptrs_i;
388 }; 318 };
389 319
390 /* Callbacks for htab_traverse. */ 320 /* Callbacks for htab_traverse. */
391 321
392 static int 322 int
393 call_count (void **slot, void *state_p) 323 ggc_call_count (ptr_data **slot, traversal_state *state)
394 { 324 {
395 struct ptr_data *d = (struct ptr_data *)*slot; 325 struct ptr_data *d = *slot;
396 struct traversal_state *state = (struct traversal_state *)state_p;
397 326
398 ggc_pch_count_object (state->d, d->obj, d->size, 327 ggc_pch_count_object (state->d, d->obj, d->size,
399 d->note_ptr_fn == gt_pch_p_S, 328 d->note_ptr_fn == gt_pch_p_S);
400 d->type);
401 state->count++; 329 state->count++;
402 return 1; 330 return 1;
403 } 331 }
404 332
405 static int 333 int
406 call_alloc (void **slot, void *state_p) 334 ggc_call_alloc (ptr_data **slot, traversal_state *state)
407 { 335 {
408 struct ptr_data *d = (struct ptr_data *)*slot; 336 struct ptr_data *d = *slot;
409 struct traversal_state *state = (struct traversal_state *)state_p;
410 337
411 d->new_addr = ggc_pch_alloc_object (state->d, d->obj, d->size, 338 d->new_addr = ggc_pch_alloc_object (state->d, d->obj, d->size,
412 d->note_ptr_fn == gt_pch_p_S, 339 d->note_ptr_fn == gt_pch_p_S);
413 d->type);
414 state->ptrs[state->ptrs_i++] = d; 340 state->ptrs[state->ptrs_i++] = d;
415 return 1; 341 return 1;
416 } 342 }
417 343
418 /* Callback for qsort. */ 344 /* Callback for qsort. */
438 364
439 if (*ptr == NULL || *ptr == (void *)1) 365 if (*ptr == NULL || *ptr == (void *)1)
440 return; 366 return;
441 367
442 result = (struct ptr_data *) 368 result = (struct ptr_data *)
443 htab_find_with_hash (saving_htab, *ptr, POINTER_HASH (*ptr)); 369 saving_htab->find_with_hash (*ptr, POINTER_HASH (*ptr));
444 gcc_assert (result); 370 gcc_assert (result);
445 *ptr = result->new_addr; 371 *ptr = result->new_addr;
446 } 372 }
447 373
448 /* Write out, after relocation, the pointers in TAB. */ 374 /* Write out, after relocation, the pointers in TAB. */
462 struct ptr_data *new_ptr; 388 struct ptr_data *new_ptr;
463 if (ptr == NULL || ptr == (void *)1) 389 if (ptr == NULL || ptr == (void *)1)
464 { 390 {
465 if (fwrite (&ptr, sizeof (void *), 1, state->f) 391 if (fwrite (&ptr, sizeof (void *), 1, state->f)
466 != 1) 392 != 1)
467 fatal_error ("can%'t write PCH file: %m"); 393 fatal_error (input_location, "can%'t write PCH file: %m");
468 } 394 }
469 else 395 else
470 { 396 {
471 new_ptr = (struct ptr_data *) 397 new_ptr = (struct ptr_data *)
472 htab_find_with_hash (saving_htab, ptr, POINTER_HASH (ptr)); 398 saving_htab->find_with_hash (ptr, POINTER_HASH (ptr));
473 if (fwrite (&new_ptr->new_addr, sizeof (void *), 1, state->f) 399 if (fwrite (&new_ptr->new_addr, sizeof (void *), 1, state->f)
474 != 1) 400 != 1)
475 fatal_error ("can%'t write PCH file: %m"); 401 fatal_error (input_location, "can%'t write PCH file: %m");
476 } 402 }
477 } 403 }
478 } 404 }
479 405
480 /* Hold the information we need to mmap the file back in. */ 406 /* Hold the information we need to mmap the file back in. */
496 size_t i; 422 size_t i;
497 struct traversal_state state; 423 struct traversal_state state;
498 char *this_object = NULL; 424 char *this_object = NULL;
499 size_t this_object_size = 0; 425 size_t this_object_size = 0;
500 struct mmap_info mmi; 426 struct mmap_info mmi;
501 const size_t mmap_offset_alignment = host_hooks.gt_pch_alloc_granularity(); 427 const size_t mmap_offset_alignment = host_hooks.gt_pch_alloc_granularity ();
502 428
503 gt_pch_save_stringpool (); 429 gt_pch_save_stringpool ();
504 430
505 timevar_push (TV_PCH_PTR_REALLOC); 431 timevar_push (TV_PCH_PTR_REALLOC);
506 saving_htab = htab_create (50000, saving_htab_hash, saving_htab_eq, free); 432 saving_htab = new hash_table<saving_hasher> (50000);
507 433
508 for (rt = gt_ggc_rtab; *rt; rt++) 434 for (rt = gt_ggc_rtab; *rt; rt++)
509 for (rti = *rt; rti->base != NULL; rti++) 435 for (rti = *rt; rti->base != NULL; rti++)
510 for (i = 0; i < rti->nelt; i++) 436 for (i = 0; i < rti->nelt; i++)
511 (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i)); 437 (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
512 438
513 for (rt = gt_pch_cache_rtab; *rt; rt++)
514 for (rti = *rt; rti->base != NULL; rti++)
515 for (i = 0; i < rti->nelt; i++)
516 (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
517
518 /* Prepare the objects for writing, determine addresses and such. */ 439 /* Prepare the objects for writing, determine addresses and such. */
519 state.f = f; 440 state.f = f;
520 state.d = init_ggc_pch (); 441 state.d = init_ggc_pch ();
521 state.count = 0; 442 state.count = 0;
522 htab_traverse (saving_htab, call_count, &state); 443 saving_htab->traverse <traversal_state *, ggc_call_count> (&state);
523 444
524 mmi.size = ggc_pch_total_size (state.d); 445 mmi.size = ggc_pch_total_size (state.d);
525 446
526 /* Try to arrange things so that no relocation is necessary, but 447 /* Try to arrange things so that no relocation is necessary, but
527 don't try very hard. On most platforms, this will always work, 448 don't try very hard. On most platforms, this will always work,
533 ggc_pch_this_base (state.d, mmi.preferred_base); 454 ggc_pch_this_base (state.d, mmi.preferred_base);
534 455
535 state.ptrs = XNEWVEC (struct ptr_data *, state.count); 456 state.ptrs = XNEWVEC (struct ptr_data *, state.count);
536 state.ptrs_i = 0; 457 state.ptrs_i = 0;
537 458
538 htab_traverse (saving_htab, call_alloc, &state); 459 saving_htab->traverse <traversal_state *, ggc_call_alloc> (&state);
539 timevar_pop (TV_PCH_PTR_REALLOC); 460 timevar_pop (TV_PCH_PTR_REALLOC);
540 461
541 timevar_push (TV_PCH_PTR_SORT); 462 timevar_push (TV_PCH_PTR_SORT);
542 qsort (state.ptrs, state.count, sizeof (*state.ptrs), compare_ptr_data); 463 qsort (state.ptrs, state.count, sizeof (*state.ptrs), compare_ptr_data);
543 timevar_pop (TV_PCH_PTR_SORT); 464 timevar_pop (TV_PCH_PTR_SORT);
544 465
545 /* Write out all the scalar variables. */ 466 /* Write out all the scalar variables. */
546 for (rt = gt_pch_scalar_rtab; *rt; rt++) 467 for (rt = gt_pch_scalar_rtab; *rt; rt++)
547 for (rti = *rt; rti->base != NULL; rti++) 468 for (rti = *rt; rti->base != NULL; rti++)
548 if (fwrite (rti->base, rti->stride, 1, f) != 1) 469 if (fwrite (rti->base, rti->stride, 1, f) != 1)
549 fatal_error ("can%'t write PCH file: %m"); 470 fatal_error (input_location, "can%'t write PCH file: %m");
550 471
551 /* Write out all the global pointers, after translation. */ 472 /* Write out all the global pointers, after translation. */
552 write_pch_globals (gt_ggc_rtab, &state); 473 write_pch_globals (gt_ggc_rtab, &state);
553 write_pch_globals (gt_pch_cache_rtab, &state);
554 474
555 /* Pad the PCH file so that the mmapped area starts on an allocation 475 /* Pad the PCH file so that the mmapped area starts on an allocation
556 granularity (usually page) boundary. */ 476 granularity (usually page) boundary. */
557 { 477 {
558 long o; 478 long o;
559 o = ftell (state.f) + sizeof (mmi); 479 o = ftell (state.f) + sizeof (mmi);
560 if (o == -1) 480 if (o == -1)
561 fatal_error ("can%'t get position in PCH file: %m"); 481 fatal_error (input_location, "can%'t get position in PCH file: %m");
562 mmi.offset = mmap_offset_alignment - o % mmap_offset_alignment; 482 mmi.offset = mmap_offset_alignment - o % mmap_offset_alignment;
563 if (mmi.offset == mmap_offset_alignment) 483 if (mmi.offset == mmap_offset_alignment)
564 mmi.offset = 0; 484 mmi.offset = 0;
565 mmi.offset += o; 485 mmi.offset += o;
566 } 486 }
567 if (fwrite (&mmi, sizeof (mmi), 1, state.f) != 1) 487 if (fwrite (&mmi, sizeof (mmi), 1, state.f) != 1)
568 fatal_error ("can%'t write PCH file: %m"); 488 fatal_error (input_location, "can%'t write PCH file: %m");
569 if (mmi.offset != 0 489 if (mmi.offset != 0
570 && fseek (state.f, mmi.offset, SEEK_SET) != 0) 490 && fseek (state.f, mmi.offset, SEEK_SET) != 0)
571 fatal_error ("can%'t write padding to PCH file: %m"); 491 fatal_error (input_location, "can%'t write padding to PCH file: %m");
572 492
573 ggc_pch_prepare_write (state.d, state.f); 493 ggc_pch_prepare_write (state.d, state.f);
494
495 #if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
496 vec<char> vbits = vNULL;
497 #endif
574 498
575 /* Actually write out the objects. */ 499 /* Actually write out the objects. */
576 for (i = 0; i < state.count; i++) 500 for (i = 0; i < state.count; i++)
577 { 501 {
578 if (this_object_size < state.ptrs[i]->size) 502 if (this_object_size < state.ptrs[i]->size)
579 { 503 {
580 this_object_size = state.ptrs[i]->size; 504 this_object_size = state.ptrs[i]->size;
581 this_object = XRESIZEVAR (char, this_object, this_object_size); 505 this_object = XRESIZEVAR (char, this_object, this_object_size);
582 } 506 }
507 #if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
508 /* obj might contain uninitialized bytes, e.g. in the trailing
509 padding of the object. Avoid warnings by making the memory
510 temporarily defined and then restoring previous state. */
511 int get_vbits = 0;
512 size_t valid_size = state.ptrs[i]->size;
513 if (__builtin_expect (RUNNING_ON_VALGRIND, 0))
514 {
515 if (vbits.length () < valid_size)
516 vbits.safe_grow (valid_size);
517 get_vbits = VALGRIND_GET_VBITS (state.ptrs[i]->obj,
518 vbits.address (), valid_size);
519 if (get_vbits == 3)
520 {
521 /* We assume that first part of obj is addressable, and
522 the rest is unaddressable. Find out where the boundary is
523 using binary search. */
524 size_t lo = 0, hi = valid_size;
525 while (hi > lo)
526 {
527 size_t mid = (lo + hi) / 2;
528 get_vbits = VALGRIND_GET_VBITS ((char *) state.ptrs[i]->obj
529 + mid, vbits.address (),
530 1);
531 if (get_vbits == 3)
532 hi = mid;
533 else if (get_vbits == 1)
534 lo = mid + 1;
535 else
536 break;
537 }
538 if (get_vbits == 1 || get_vbits == 3)
539 {
540 valid_size = lo;
541 get_vbits = VALGRIND_GET_VBITS (state.ptrs[i]->obj,
542 vbits.address (),
543 valid_size);
544 }
545 }
546 if (get_vbits == 1)
547 VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (state.ptrs[i]->obj,
548 state.ptrs[i]->size));
549 }
550 #endif
583 memcpy (this_object, state.ptrs[i]->obj, state.ptrs[i]->size); 551 memcpy (this_object, state.ptrs[i]->obj, state.ptrs[i]->size);
584 if (state.ptrs[i]->reorder_fn != NULL) 552 if (state.ptrs[i]->reorder_fn != NULL)
585 state.ptrs[i]->reorder_fn (state.ptrs[i]->obj, 553 state.ptrs[i]->reorder_fn (state.ptrs[i]->obj,
586 state.ptrs[i]->note_ptr_cookie, 554 state.ptrs[i]->note_ptr_cookie,
587 relocate_ptrs, &state); 555 relocate_ptrs, &state);
591 ggc_pch_write_object (state.d, state.f, state.ptrs[i]->obj, 559 ggc_pch_write_object (state.d, state.f, state.ptrs[i]->obj,
592 state.ptrs[i]->new_addr, state.ptrs[i]->size, 560 state.ptrs[i]->new_addr, state.ptrs[i]->size,
593 state.ptrs[i]->note_ptr_fn == gt_pch_p_S); 561 state.ptrs[i]->note_ptr_fn == gt_pch_p_S);
594 if (state.ptrs[i]->note_ptr_fn != gt_pch_p_S) 562 if (state.ptrs[i]->note_ptr_fn != gt_pch_p_S)
595 memcpy (state.ptrs[i]->obj, this_object, state.ptrs[i]->size); 563 memcpy (state.ptrs[i]->obj, this_object, state.ptrs[i]->size);
564 #if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
565 if (__builtin_expect (get_vbits == 1, 0))
566 {
567 (void) VALGRIND_SET_VBITS (state.ptrs[i]->obj, vbits.address (),
568 valid_size);
569 if (valid_size != state.ptrs[i]->size)
570 VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *)
571 state.ptrs[i]->obj
572 + valid_size,
573 state.ptrs[i]->size
574 - valid_size));
575 }
576 #endif
596 } 577 }
578 #if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
579 vbits.release ();
580 #endif
581
597 ggc_pch_finish (state.d, state.f); 582 ggc_pch_finish (state.d, state.f);
598 gt_pch_fixup_stringpool (); 583 gt_pch_fixup_stringpool ();
599 584
600 free (state.ptrs); 585 XDELETE (state.ptrs);
601 htab_delete (saving_htab); 586 XDELETE (this_object);
587 delete saving_htab;
588 saving_htab = NULL;
602 } 589 }
603 590
604 /* Read the state of the compiler back in from F. */ 591 /* Read the state of the compiler back in from F. */
605 592
606 void 593 void
621 608
622 /* Read in all the scalar variables. */ 609 /* Read in all the scalar variables. */
623 for (rt = gt_pch_scalar_rtab; *rt; rt++) 610 for (rt = gt_pch_scalar_rtab; *rt; rt++)
624 for (rti = *rt; rti->base != NULL; rti++) 611 for (rti = *rt; rti->base != NULL; rti++)
625 if (fread (rti->base, rti->stride, 1, f) != 1) 612 if (fread (rti->base, rti->stride, 1, f) != 1)
626 fatal_error ("can%'t read PCH file: %m"); 613 fatal_error (input_location, "can%'t read PCH file: %m");
627 614
628 /* Read in all the global pointers, in 6 easy loops. */ 615 /* Read in all the global pointers, in 6 easy loops. */
629 for (rt = gt_ggc_rtab; *rt; rt++) 616 for (rt = gt_ggc_rtab; *rt; rt++)
630 for (rti = *rt; rti->base != NULL; rti++) 617 for (rti = *rt; rti->base != NULL; rti++)
631 for (i = 0; i < rti->nelt; i++) 618 for (i = 0; i < rti->nelt; i++)
632 if (fread ((char *)rti->base + rti->stride * i, 619 if (fread ((char *)rti->base + rti->stride * i,
633 sizeof (void *), 1, f) != 1) 620 sizeof (void *), 1, f) != 1)
634 fatal_error ("can%'t read PCH file: %m"); 621 fatal_error (input_location, "can%'t read PCH file: %m");
635
636 for (rt = gt_pch_cache_rtab; *rt; rt++)
637 for (rti = *rt; rti->base != NULL; rti++)
638 for (i = 0; i < rti->nelt; i++)
639 if (fread ((char *)rti->base + rti->stride * i,
640 sizeof (void *), 1, f) != 1)
641 fatal_error ("can%'t read PCH file: %m");
642 622
643 if (fread (&mmi, sizeof (mmi), 1, f) != 1) 623 if (fread (&mmi, sizeof (mmi), 1, f) != 1)
644 fatal_error ("can%'t read PCH file: %m"); 624 fatal_error (input_location, "can%'t read PCH file: %m");
645 625
646 result = host_hooks.gt_pch_use_address (mmi.preferred_base, mmi.size, 626 result = host_hooks.gt_pch_use_address (mmi.preferred_base, mmi.size,
647 fileno (f), mmi.offset); 627 fileno (f), mmi.offset);
648 if (result < 0) 628 if (result < 0)
649 fatal_error ("had to relocate PCH"); 629 fatal_error (input_location, "had to relocate PCH");
650 if (result == 0) 630 if (result == 0)
651 { 631 {
652 if (fseek (f, mmi.offset, SEEK_SET) != 0 632 if (fseek (f, mmi.offset, SEEK_SET) != 0
653 || fread (mmi.preferred_base, mmi.size, 1, f) != 1) 633 || fread (mmi.preferred_base, mmi.size, 1, f) != 1)
654 fatal_error ("can%'t read PCH file: %m"); 634 fatal_error (input_location, "can%'t read PCH file: %m");
655 } 635 }
656 else if (fseek (f, mmi.offset + mmi.size, SEEK_SET) != 0) 636 else if (fseek (f, mmi.offset + mmi.size, SEEK_SET) != 0)
657 fatal_error ("can%'t read PCH file: %m"); 637 fatal_error (input_location, "can%'t read PCH file: %m");
658 638
659 ggc_pch_read (f, mmi.preferred_base); 639 ggc_pch_read (f, mmi.preferred_base);
660 640
661 gt_pch_restore_stringpool (); 641 gt_pch_restore_stringpool ();
662 } 642 }
691 same as pagesize. */ 671 same as pagesize. */
692 672
693 size_t 673 size_t
694 default_gt_pch_alloc_granularity (void) 674 default_gt_pch_alloc_granularity (void)
695 { 675 {
696 return getpagesize(); 676 return getpagesize ();
697 } 677 }
698 678
699 #if HAVE_MMAP_FILE 679 #if HAVE_MMAP_FILE
700 /* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is present. 680 /* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is present.
701 We temporarily allocate SIZE bytes, and let the kernel place the data 681 We temporarily allocate SIZE bytes, and let the kernel place the data
779 759
780 /* Heuristic to set a default for GGC_MIN_EXPAND. */ 760 /* Heuristic to set a default for GGC_MIN_EXPAND. */
781 static int 761 static int
782 ggc_min_expand_heuristic (void) 762 ggc_min_expand_heuristic (void)
783 { 763 {
784 double min_expand = physmem_total(); 764 double min_expand = physmem_total ();
785 765
786 /* Adjust for rlimits. */ 766 /* Adjust for rlimits. */
787 min_expand = ggc_rlimit_bound (min_expand); 767 min_expand = ggc_rlimit_bound (min_expand);
788 768
789 /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding 769 /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding
798 778
799 /* Heuristic to set a default for GGC_MIN_HEAPSIZE. */ 779 /* Heuristic to set a default for GGC_MIN_HEAPSIZE. */
800 static int 780 static int
801 ggc_min_heapsize_heuristic (void) 781 ggc_min_heapsize_heuristic (void)
802 { 782 {
803 double phys_kbytes = physmem_total(); 783 double phys_kbytes = physmem_total ();
804 double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2); 784 double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2);
805 785
806 phys_kbytes /= 1024; /* Convert to Kbytes. */ 786 phys_kbytes /= 1024; /* Convert to Kbytes. */
807 limit_kbytes /= 1024; 787 limit_kbytes /= 1024;
808 788
843 set_default_param_value (GGC_MIN_EXPAND, ggc_min_expand_heuristic ()); 823 set_default_param_value (GGC_MIN_EXPAND, ggc_min_expand_heuristic ());
844 set_default_param_value (GGC_MIN_HEAPSIZE, ggc_min_heapsize_heuristic ()); 824 set_default_param_value (GGC_MIN_HEAPSIZE, ggc_min_heapsize_heuristic ());
845 #endif 825 #endif
846 } 826 }
847 827
848 #ifdef GATHER_STATISTICS 828 /* GGC memory usage. */
849 829 struct ggc_usage: public mem_usage
850 /* Datastructure used to store per-call-site statistics. */ 830 {
851 struct loc_descriptor 831 /* Default constructor. */
852 { 832 ggc_usage (): m_freed (0), m_collected (0), m_overhead (0) {}
853 const char *file; 833 /* Constructor. */
854 int line; 834 ggc_usage (size_t allocated, size_t times, size_t peak,
855 const char *function; 835 size_t freed, size_t collected, size_t overhead)
856 int times; 836 : mem_usage (allocated, times, peak),
857 size_t allocated; 837 m_freed (freed), m_collected (collected), m_overhead (overhead) {}
858 size_t overhead; 838
859 size_t freed; 839 /* Comparison operator. */
860 size_t collected; 840 inline bool
841 operator< (const ggc_usage &second) const
842 {
843 return (get_balance () == second.get_balance () ?
844 (m_peak == second.m_peak ? m_times < second.m_times
845 : m_peak < second.m_peak)
846 : get_balance () < second.get_balance ());
847 }
848
849 /* Register overhead of ALLOCATED and OVERHEAD bytes. */
850 inline void
851 register_overhead (size_t allocated, size_t overhead)
852 {
853 m_allocated += allocated;
854 m_overhead += overhead;
855 m_times++;
856 }
857
858 /* Release overhead of SIZE bytes. */
859 inline void
860 release_overhead (size_t size)
861 {
862 m_freed += size;
863 }
864
865 /* Sum the usage with SECOND usage. */
866 ggc_usage
867 operator+ (const ggc_usage &second)
868 {
869 return ggc_usage (m_allocated + second.m_allocated,
870 m_times + second.m_times,
871 m_peak + second.m_peak,
872 m_freed + second.m_freed,
873 m_collected + second.m_collected,
874 m_overhead + second.m_overhead);
875 }
876
877 /* Dump usage with PREFIX, where TOTAL is sum of all rows. */
878 inline void
879 dump (const char *prefix, ggc_usage &total) const
880 {
881 long balance = get_balance ();
882 fprintf (stderr,
883 "%-48s %10li:%5.1f%%%10li:%5.1f%%"
884 "%10li:%5.1f%%%10li:%5.1f%%%10li\n",
885 prefix, (long)m_collected,
886 get_percent (m_collected, total.m_collected),
887 (long)m_freed, get_percent (m_freed, total.m_freed),
888 (long)balance, get_percent (balance, total.get_balance ()),
889 (long)m_overhead, get_percent (m_overhead, total.m_overhead),
890 (long)m_times);
891 }
892
893 /* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */
894 inline void
895 dump (mem_location *loc, ggc_usage &total) const
896 {
897 char *location_string = loc->to_string ();
898
899 dump (location_string, total);
900
901 free (location_string);
902 }
903
904 /* Dump footer. */
905 inline void
906 dump_footer ()
907 {
908 print_dash_line ();
909 dump ("Total", *this);
910 print_dash_line ();
911 }
912
913 /* Get balance which is GGC allocation leak. */
914 inline long
915 get_balance () const
916 {
917 return m_allocated + m_overhead - m_collected - m_freed;
918 }
919
920 typedef std::pair<mem_location *, ggc_usage *> mem_pair_t;
921
922 /* Compare wrapper used by qsort method. */
923 static int
924 compare (const void *first, const void *second)
925 {
926 const mem_pair_t f = *(const mem_pair_t *)first;
927 const mem_pair_t s = *(const mem_pair_t *)second;
928
929 return (*f.second) < (*s.second);
930 }
931
932 /* Compare rows in final GGC summary dump. */
933 static int
934 compare_final (const void *first, const void *second)
935 {
936 typedef std::pair<mem_location *, ggc_usage *> mem_pair_t;
937
938 const ggc_usage *f = ((const mem_pair_t *)first)->second;
939 const ggc_usage *s = ((const mem_pair_t *)second)->second;
940
941 size_t a = f->m_allocated + f->m_overhead - f->m_freed;
942 size_t b = s->m_allocated + s->m_overhead - s->m_freed;
943
944 return a == b ? 0 : (a < b ? 1 : -1);
945 }
946
947 /* Dump header with NAME. */
948 static inline void
949 dump_header (const char *name)
950 {
951 fprintf (stderr, "%-48s %11s%17s%17s%16s%17s\n", name, "Garbage", "Freed",
952 "Leak", "Overhead", "Times");
953 print_dash_line ();
954 }
955
956 /* Freed memory in bytes. */
957 size_t m_freed;
958 /* Collected memory in bytes. */
959 size_t m_collected;
960 /* Overhead memory in bytes. */
961 size_t m_overhead;
861 }; 962 };
862 963
863 /* Hashtable used for statistics. */ 964 /* GCC memory description. */
864 static htab_t loc_hash; 965 static mem_alloc_description<ggc_usage> ggc_mem_desc;
865 966
866 /* Hash table helpers functions. */ 967 /* Dump per-site memory statistics. */
867 static hashval_t 968
868 hash_descriptor (const void *p) 969 void
869 { 970 dump_ggc_loc_statistics (bool final)
870 const struct loc_descriptor *const d = (const struct loc_descriptor *) p; 971 {
871 972 if (! GATHER_STATISTICS)
872 return htab_hash_pointer (d->function) | d->line; 973 return;
873 } 974
874 975 ggc_force_collect = true;
875 static int 976 ggc_collect ();
876 eq_descriptor (const void *p1, const void *p2) 977
877 { 978 ggc_mem_desc.dump (GGC_ORIGIN, final ? ggc_usage::compare_final : NULL);
878 const struct loc_descriptor *const d = (const struct loc_descriptor *) p1; 979
879 const struct loc_descriptor *const d2 = (const struct loc_descriptor *) p2; 980 ggc_force_collect = false;
880
881 return (d->file == d2->file && d->line == d2->line
882 && d->function == d2->function);
883 }
884
885 /* Hashtable converting address of allocated field to loc descriptor. */
886 static htab_t ptr_hash;
887 struct ptr_hash_entry
888 {
889 void *ptr;
890 struct loc_descriptor *loc;
891 size_t size;
892 };
893
894 /* Hash table helpers functions. */
895 static hashval_t
896 hash_ptr (const void *p)
897 {
898 const struct ptr_hash_entry *const d = (const struct ptr_hash_entry *) p;
899
900 return htab_hash_pointer (d->ptr);
901 }
902
903 static int
904 eq_ptr (const void *p1, const void *p2)
905 {
906 const struct ptr_hash_entry *const p = (const struct ptr_hash_entry *) p1;
907
908 return (p->ptr == p2);
909 }
910
911 /* Return descriptor for given call site, create new one if needed. */
912 static struct loc_descriptor *
913 loc_descriptor (const char *name, int line, const char *function)
914 {
915 struct loc_descriptor loc;
916 struct loc_descriptor **slot;
917
918 loc.file = name;
919 loc.line = line;
920 loc.function = function;
921 if (!loc_hash)
922 loc_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
923
924 slot = (struct loc_descriptor **) htab_find_slot (loc_hash, &loc, INSERT);
925 if (*slot)
926 return *slot;
927 *slot = XCNEW (struct loc_descriptor);
928 (*slot)->file = name;
929 (*slot)->line = line;
930 (*slot)->function = function;
931 return *slot;
932 } 981 }
933 982
934 /* Record ALLOCATED and OVERHEAD bytes to descriptor NAME:LINE (FUNCTION). */ 983 /* Record ALLOCATED and OVERHEAD bytes to descriptor NAME:LINE (FUNCTION). */
935 void 984 void
936 ggc_record_overhead (size_t allocated, size_t overhead, void *ptr, 985 ggc_record_overhead (size_t allocated, size_t overhead, void *ptr MEM_STAT_DECL)
937 const char *name, int line, const char *function) 986 {
938 { 987 ggc_usage *usage = ggc_mem_desc.register_descriptor (ptr, GGC_ORIGIN, false
939 struct loc_descriptor *loc = loc_descriptor (name, line, function); 988 FINAL_PASS_MEM_STAT);
940 struct ptr_hash_entry *p = XNEW (struct ptr_hash_entry); 989
941 PTR *slot; 990 ggc_mem_desc.register_object_overhead (usage, allocated + overhead, ptr);
942 991 usage->register_overhead (allocated, overhead);
943 p->ptr = ptr; 992 }
944 p->loc = loc; 993
945 p->size = allocated + overhead; 994 /* Notice that the pointer has been freed. */
946 if (!ptr_hash) 995 void
947 ptr_hash = htab_create (10, hash_ptr, eq_ptr, NULL); 996 ggc_free_overhead (void *ptr)
948 slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer (ptr), INSERT); 997 {
949 gcc_assert (!*slot); 998 ggc_mem_desc.release_object_overhead (ptr);
950 *slot = p;
951
952 loc->times++;
953 loc->allocated+=allocated;
954 loc->overhead+=overhead;
955 }
956
957 /* Helper function for prune_overhead_list. See if SLOT is still marked and
958 remove it from hashtable if it is not. */
959 static int
960 ggc_prune_ptr (void **slot, void *b ATTRIBUTE_UNUSED)
961 {
962 struct ptr_hash_entry *p = (struct ptr_hash_entry *) *slot;
963 if (!ggc_marked_p (p->ptr))
964 {
965 p->loc->collected += p->size;
966 htab_clear_slot (ptr_hash, slot);
967 free (p);
968 }
969 return 1;
970 } 999 }
971 1000
972 /* After live values has been marked, walk all recorded pointers and see if 1001 /* After live values has been marked, walk all recorded pointers and see if
973 they are still live. */ 1002 they are still live. */
974 void 1003 void
975 ggc_prune_overhead_list (void) 1004 ggc_prune_overhead_list (void)
976 { 1005 {
977 htab_traverse (ptr_hash, ggc_prune_ptr, NULL); 1006 typedef hash_map<const void *, std::pair<ggc_usage *, size_t > > map_t;
978 } 1007
979 1008 map_t::iterator it = ggc_mem_desc.m_reverse_object_map->begin ();
980 /* Notice that the pointer has been freed. */ 1009
981 void 1010 for (; it != ggc_mem_desc.m_reverse_object_map->end (); ++it)
982 ggc_free_overhead (void *ptr) 1011 if (!ggc_marked_p ((*it).first))
983 { 1012 (*it).second.first->m_collected += (*it).second.second;
984 PTR *slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer (ptr), 1013
985 NO_INSERT); 1014 delete ggc_mem_desc.m_reverse_object_map;
986 struct ptr_hash_entry *p; 1015 ggc_mem_desc.m_reverse_object_map = new map_t (13, false, false);
987 /* The pointer might be not found if a PCH read happened between allocation 1016 }
988 and ggc_free () call. FIXME: account memory properly in the presence of
989 PCH. */
990 if (!slot)
991 return;
992 p = (struct ptr_hash_entry *) *slot;
993 p->loc->freed += p->size;
994 htab_clear_slot (ptr_hash, slot);
995 free (p);
996 }
997
998 /* Helper for qsort; sort descriptors by amount of memory consumed. */
999 static int
1000 final_cmp_statistic (const void *loc1, const void *loc2)
1001 {
1002 const struct loc_descriptor *const l1 =
1003 *(const struct loc_descriptor *const *) loc1;
1004 const struct loc_descriptor *const l2 =
1005 *(const struct loc_descriptor *const *) loc2;
1006 long diff;
1007 diff = ((long)(l1->allocated + l1->overhead - l1->freed) -
1008 (l2->allocated + l2->overhead - l2->freed));
1009 return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1010 }
1011
1012 /* Helper for qsort; sort descriptors by amount of memory consumed. */
1013 static int
1014 cmp_statistic (const void *loc1, const void *loc2)
1015 {
1016 const struct loc_descriptor *const l1 =
1017 *(const struct loc_descriptor *const *) loc1;
1018 const struct loc_descriptor *const l2 =
1019 *(const struct loc_descriptor *const *) loc2;
1020 long diff;
1021
1022 diff = ((long)(l1->allocated + l1->overhead - l1->freed - l1->collected) -
1023 (l2->allocated + l2->overhead - l2->freed - l2->collected));
1024 if (diff)
1025 return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1026 diff = ((long)(l1->allocated + l1->overhead - l1->freed) -
1027 (l2->allocated + l2->overhead - l2->freed));
1028 return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1029 }
1030
1031 /* Collect array of the descriptors from hashtable. */
1032 static struct loc_descriptor **loc_array;
1033 static int
1034 add_statistics (void **slot, void *b)
1035 {
1036 int *n = (int *)b;
1037 loc_array[*n] = (struct loc_descriptor *) *slot;
1038 (*n)++;
1039 return 1;
1040 }
1041
1042 /* Dump per-site memory statistics. */
1043 #endif
1044 void
1045 dump_ggc_loc_statistics (bool final ATTRIBUTE_UNUSED)
1046 {
1047 #ifdef GATHER_STATISTICS
1048 int nentries = 0;
1049 char s[4096];
1050 size_t collected = 0, freed = 0, allocated = 0, overhead = 0, times = 0;
1051 int i;
1052
1053 ggc_force_collect = true;
1054 ggc_collect ();
1055
1056 loc_array = XCNEWVEC (struct loc_descriptor *, loc_hash->n_elements);
1057 fprintf (stderr, "-------------------------------------------------------\n");
1058 fprintf (stderr, "\n%-48s %10s %10s %10s %10s %10s\n",
1059 "source location", "Garbage", "Freed", "Leak", "Overhead", "Times");
1060 fprintf (stderr, "-------------------------------------------------------\n");
1061 htab_traverse (loc_hash, add_statistics, &nentries);
1062 qsort (loc_array, nentries, sizeof (*loc_array),
1063 final ? final_cmp_statistic : cmp_statistic);
1064 for (i = 0; i < nentries; i++)
1065 {
1066 struct loc_descriptor *d = loc_array[i];
1067 allocated += d->allocated;
1068 times += d->times;
1069 freed += d->freed;
1070 collected += d->collected;
1071 overhead += d->overhead;
1072 }
1073 for (i = 0; i < nentries; i++)
1074 {
1075 struct loc_descriptor *d = loc_array[i];
1076 if (d->allocated)
1077 {
1078 const char *s1 = d->file;
1079 const char *s2;
1080 while ((s2 = strstr (s1, "gcc/")))
1081 s1 = s2 + 4;
1082 sprintf (s, "%s:%i (%s)", s1, d->line, d->function);
1083 s[48] = 0;
1084 fprintf (stderr, "%-48s %10li:%4.1f%% %10li:%4.1f%% %10li:%4.1f%% %10li:%4.1f%% %10li\n", s,
1085 (long)d->collected,
1086 (d->collected) * 100.0 / collected,
1087 (long)d->freed,
1088 (d->freed) * 100.0 / freed,
1089 (long)(d->allocated + d->overhead - d->freed - d->collected),
1090 (d->allocated + d->overhead - d->freed - d->collected) * 100.0
1091 / (allocated + overhead - freed - collected),
1092 (long)d->overhead,
1093 d->overhead * 100.0 / overhead,
1094 (long)d->times);
1095 }
1096 }
1097 fprintf (stderr, "%-48s %10ld %10ld %10ld %10ld %10ld\n",
1098 "Total", (long)collected, (long)freed,
1099 (long)(allocated + overhead - freed - collected), (long)overhead,
1100 (long)times);
1101 fprintf (stderr, "%-48s %10s %10s %10s %10s %10s\n",
1102 "source location", "Garbage", "Freed", "Leak", "Overhead", "Times");
1103 fprintf (stderr, "-------------------------------------------------------\n");
1104 ggc_force_collect = false;
1105 #endif
1106 }