]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ggc-common.c
generalized IPA predicate on parameter
[thirdparty/gcc.git] / gcc / ggc-common.c
CommitLineData
bebb7b68 1/* Simple garbage collection for the GNU compiler.
fbd26352 2 Copyright (C) 1999-2019 Free Software Foundation, Inc.
bebb7b68 3
f12b58b3 4This file is part of GCC.
bebb7b68 5
f12b58b3 6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8c4c00c1 8Software Foundation; either version 3, or (at your option) any later
f12b58b3 9version.
bebb7b68 10
f12b58b3 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
155b05dc 13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
bebb7b68 15
155b05dc 16You should have received a copy of the GNU General Public License
8c4c00c1 17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
bebb7b68 19
20/* Generic garbage collection (GC) functions and data, not specific to
21 any particular GC implementation. */
22
23#include "config.h"
24#include "system.h"
805e22b2 25#include "coretypes.h"
7c29e30e 26#include "timevar.h"
0b205f4c 27#include "diagnostic-core.h"
7c29e30e 28#include "ggc-internal.h"
dbcfd357 29#include "params.h"
ddf4604f 30#include "hosthooks.h"
740cd0be 31#include "plugin.h"
573aba85 32
0ca9a7b6 33/* When set, ggc_collect will do collection. */
34bool ggc_force_collect;
35
dfecde36 36/* When true, protect the contents of the identifier hash table. */
37bool ggc_protect_identifiers = true;
38
4e00b6fd 39/* Statistics about the allocation. */
40static ggc_statistics *ggc_stats;
41
573aba85 42struct traversal_state;
43
6ec1f4e0 44static int compare_ptr_data (const void *, const void *);
45static void relocate_ptrs (void *, void *);
46static void write_pch_globals (const struct ggc_root_tab * const *tab,
47 struct traversal_state *state);
bebb7b68 48
49/* Maintain global roots that are preserved during GC. */
50
740cd0be 51/* This extra vector of dynamically registered root_tab-s is used by
52 ggc_mark_roots and gives the ability to dynamically add new GGC root
86b63696 53 tables, for instance from some plugins; this vector is on the heap
54 since it is used by GGC internally. */
55typedef const struct ggc_root_tab *const_ggc_root_tab_t;
f1f41a6c 56static vec<const_ggc_root_tab_t> extra_root_vec;
740cd0be 57
740cd0be 58/* Dynamically register a new GGC root table RT. This is useful for
59 plugins. */
60
48e1416a 61void
740cd0be 62ggc_register_root_tab (const struct ggc_root_tab* rt)
63{
86b63696 64 if (rt)
f1f41a6c 65 extra_root_vec.safe_push (rt);
740cd0be 66}
67
c03efe25 68/* Mark all the roots in the table RT. */
69
70static void
71ggc_mark_root_tab (const_ggc_root_tab_t rt)
72{
73 size_t i;
74
75 for ( ; rt->base != NULL; rt++)
76 for (i = 0; i < rt->nelt; i++)
77 (*rt->cb) (*(void **) ((char *)rt->base + rt->stride * i));
78}
79
e3c4633e 80/* Iterate through all registered roots and mark each element. */
81
bebb7b68 82void
6ec1f4e0 83ggc_mark_roots (void)
0046a2c2 84{
1f3233d1 85 const struct ggc_root_tab *const *rt;
c03efe25 86 const_ggc_root_tab_t rtp, rti;
1f3233d1 87 size_t i;
3cfec666 88
1f3233d1 89 for (rt = gt_ggc_deletable_rtab; *rt; rt++)
90 for (rti = *rt; rti->base != NULL; rti++)
91 memset (rti->base, 0, rti->stride);
92
93 for (rt = gt_ggc_rtab; *rt; rt++)
c03efe25 94 ggc_mark_root_tab (*rt);
740cd0be 95
f1f41a6c 96 FOR_EACH_VEC_ELT (extra_root_vec, i, rtp)
c03efe25 97 ggc_mark_root_tab (rtp);
769177ac 98
dfecde36 99 if (ggc_protect_identifiers)
100 ggc_mark_stringpool ();
769177ac 101
f863a586 102 gt_clear_caches ();
103
dfecde36 104 if (! ggc_protect_identifiers)
105 ggc_purge_stringpool ();
740cd0be 106
107 /* Some plugins may call ggc_set_mark from here. */
108 invoke_plugin_callbacks (PLUGIN_GGC_MARKING, NULL);
0046a2c2 109}
110
1f3233d1 111/* Allocate a block of memory, then clear it. */
112void *
92f06184 113ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t s, size_t n
114 MEM_STAT_DECL)
cf6cce73 115{
92f06184 116 void *buf = ggc_internal_alloc (size, f, s, n PASS_MEM_STAT);
1f3233d1 117 memset (buf, 0, size);
118 return buf;
cf6cce73 119}
120
1f3233d1 121/* Resize a block of memory, possibly re-allocating it. */
122void *
881f903e 123ggc_realloc (void *x, size_t size MEM_STAT_DECL)
cf6cce73 124{
1f3233d1 125 void *r;
126 size_t old_size;
cf6cce73 127
1f3233d1 128 if (x == NULL)
881f903e 129 return ggc_internal_alloc (size PASS_MEM_STAT);
cf6cce73 130
1f3233d1 131 old_size = ggc_get_size (x);
c4e03242 132
1f3233d1 133 if (size <= old_size)
dd359afe 134 {
135 /* Mark the unwanted memory as unaccessible. We also need to make
136 the "new" size accessible, since ggc_get_size returns the size of
137 the pool, not the size of the individually allocated object, the
138 size which was previously made accessible. Unfortunately, we
139 don't know that previously allocated size. Without that
140 knowledge we have to lose some initialization-tracking for the
141 old parts of the object. An alternative is to mark the whole
6ec1f4e0 142 old_size as reachable, but that would lose tracking of writes
dd359afe 143 after the end of the object (by small offsets). Discard the
144 handle to avoid handle leak. */
a7779e75 145 VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *) x + size,
146 old_size - size));
147 VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (x, size));
dd359afe 148 return x;
149 }
cf6cce73 150
881f903e 151 r = ggc_internal_alloc (size PASS_MEM_STAT);
dd359afe 152
153 /* Since ggc_get_size returns the size of the pool, not the size of the
154 individually allocated object, we'd access parts of the old object
155 that were marked invalid with the memcpy below. We lose a bit of the
156 initialization-tracking since some of it may be uninitialized. */
a7779e75 157 VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (x, old_size));
dd359afe 158
1f3233d1 159 memcpy (r, x, old_size);
dd359afe 160
161 /* The old object is not supposed to be used anymore. */
c4e03242 162 ggc_free (x);
dd359afe 163
1f3233d1 164 return r;
cf6cce73 165}
166
791ceafe 167void *
ba72912a 168ggc_cleared_alloc_htab_ignore_args (size_t c ATTRIBUTE_UNUSED,
169 size_t n ATTRIBUTE_UNUSED)
791ceafe 170{
ba72912a 171 gcc_assert (c * n == sizeof (struct htab));
25a27413 172 return ggc_cleared_alloc<htab> ();
ba72912a 173}
174
175/* TODO: once we actually use type information in GGC, create a new tag
176 gt_gcc_ptr_array and use it for pointer arrays. */
177void *
178ggc_cleared_alloc_ptr_array_two_args (size_t c, size_t n)
179{
180 gcc_assert (sizeof (PTR *) == n);
25a27413 181 return ggc_cleared_vec_alloc<PTR *> (c);
791ceafe 182}
183
573aba85 184/* These are for splay_tree_new_ggc. */
6ec1f4e0 185void *
5cc13354 186ggc_splay_alloc (int sz, void *nl)
573aba85 187{
0d59b19d 188 gcc_assert (!nl);
ba72912a 189 return ggc_internal_alloc (sz);
573aba85 190}
191
192void
6ec1f4e0 193ggc_splay_dont_free (void * x ATTRIBUTE_UNUSED, void *nl)
573aba85 194{
0d59b19d 195 gcc_assert (!nl);
573aba85 196}
197
4e00b6fd 198void
6ec1f4e0 199ggc_print_common_statistics (FILE *stream ATTRIBUTE_UNUSED,
200 ggc_statistics *stats)
4e00b6fd 201{
4e00b6fd 202 /* Set the pointer so that during collection we will actually gather
203 the statistics. */
204 ggc_stats = stats;
205
206 /* Then do one collection to fill in the statistics. */
207 ggc_collect ();
208
573aba85 209 /* At present, we don't really gather any interesting statistics. */
210
211 /* Don't gather statistics any more. */
212 ggc_stats = NULL;
213}
214\f
215/* Functions for saving and restoring GCable memory to disk. */
216
6ec1f4e0 217struct ptr_data
573aba85 218{
219 void *obj;
220 void *note_ptr_cookie;
221 gt_note_pointers note_ptr_fn;
222 gt_handle_reorder reorder_fn;
223 size_t size;
224 void *new_addr;
225};
226
5df02853 227#define POINTER_HASH(x) (hashval_t)((intptr_t)x >> 3)
573aba85 228
d9dd21a8 229/* Helper for hashing saving_htab. */
230
298e7f9a 231struct saving_hasher : free_ptr_hash <ptr_data>
d9dd21a8 232{
9969c043 233 typedef void *compare_type;
234 static inline hashval_t hash (const ptr_data *);
235 static inline bool equal (const ptr_data *, const void *);
d9dd21a8 236};
237
238inline hashval_t
9969c043 239saving_hasher::hash (const ptr_data *p)
d9dd21a8 240{
241 return POINTER_HASH (p->obj);
242}
243
244inline bool
9969c043 245saving_hasher::equal (const ptr_data *p1, const void *p2)
d9dd21a8 246{
247 return p1->obj == p2;
248}
249
c1f445d2 250static hash_table<saving_hasher> *saving_htab;
d9dd21a8 251
573aba85 252/* Register an object in the hash table. */
253
254int
6ec1f4e0 255gt_pch_note_object (void *obj, void *note_ptr_cookie,
5cc13354 256 gt_note_pointers note_ptr_fn)
573aba85 257{
258 struct ptr_data **slot;
6ec1f4e0 259
573aba85 260 if (obj == NULL || obj == (void *) 1)
261 return 0;
262
263 slot = (struct ptr_data **)
c1f445d2 264 saving_htab->find_slot_with_hash (obj, POINTER_HASH (obj), INSERT);
573aba85 265 if (*slot != NULL)
266 {
0d59b19d 267 gcc_assert ((*slot)->note_ptr_fn == note_ptr_fn
268 && (*slot)->note_ptr_cookie == note_ptr_cookie);
573aba85 269 return 0;
270 }
6ec1f4e0 271
4077bf7a 272 *slot = XCNEW (struct ptr_data);
573aba85 273 (*slot)->obj = obj;
274 (*slot)->note_ptr_fn = note_ptr_fn;
275 (*slot)->note_ptr_cookie = note_ptr_cookie;
276 if (note_ptr_fn == gt_pch_p_S)
4077bf7a 277 (*slot)->size = strlen ((const char *)obj) + 1;
573aba85 278 else
279 (*slot)->size = ggc_get_size (obj);
280 return 1;
281}
282
283/* Register an object in the hash table. */
284
285void
6ec1f4e0 286gt_pch_note_reorder (void *obj, void *note_ptr_cookie,
287 gt_handle_reorder reorder_fn)
573aba85 288{
289 struct ptr_data *data;
6ec1f4e0 290
573aba85 291 if (obj == NULL || obj == (void *) 1)
292 return;
293
4077bf7a 294 data = (struct ptr_data *)
c1f445d2 295 saving_htab->find_with_hash (obj, POINTER_HASH (obj));
0d59b19d 296 gcc_assert (data && data->note_ptr_cookie == note_ptr_cookie);
6ec1f4e0 297
573aba85 298 data->reorder_fn = reorder_fn;
299}
300
573aba85 301/* Handy state for the traversal functions. */
302
6ec1f4e0 303struct traversal_state
573aba85 304{
305 FILE *f;
306 struct ggc_pch_data *d;
307 size_t count;
308 struct ptr_data **ptrs;
309 size_t ptrs_i;
310};
311
312/* Callbacks for htab_traverse. */
313
d9dd21a8 314int
315ggc_call_count (ptr_data **slot, traversal_state *state)
573aba85 316{
d9dd21a8 317 struct ptr_data *d = *slot;
6ec1f4e0 318
1bb42c87 319 ggc_pch_count_object (state->d, d->obj, d->size,
5cc13354 320 d->note_ptr_fn == gt_pch_p_S);
573aba85 321 state->count++;
322 return 1;
323}
324
d9dd21a8 325int
326ggc_call_alloc (ptr_data **slot, traversal_state *state)
573aba85 327{
d9dd21a8 328 struct ptr_data *d = *slot;
6ec1f4e0 329
1bb42c87 330 d->new_addr = ggc_pch_alloc_object (state->d, d->obj, d->size,
5cc13354 331 d->note_ptr_fn == gt_pch_p_S);
573aba85 332 state->ptrs[state->ptrs_i++] = d;
333 return 1;
334}
335
336/* Callback for qsort. */
337
338static int
6ec1f4e0 339compare_ptr_data (const void *p1_p, const void *p2_p)
573aba85 340{
9f627b1a 341 const struct ptr_data *const p1 = *(const struct ptr_data *const *)p1_p;
342 const struct ptr_data *const p2 = *(const struct ptr_data *const *)p2_p;
573aba85 343 return (((size_t)p1->new_addr > (size_t)p2->new_addr)
344 - ((size_t)p1->new_addr < (size_t)p2->new_addr));
345}
346
347/* Callbacks for note_ptr_fn. */
348
349static void
6ec1f4e0 350relocate_ptrs (void *ptr_p, void *state_p)
573aba85 351{
352 void **ptr = (void **)ptr_p;
6ec1f4e0 353 struct traversal_state *state ATTRIBUTE_UNUSED
573aba85 354 = (struct traversal_state *)state_p;
355 struct ptr_data *result;
356
357 if (*ptr == NULL || *ptr == (void *)1)
358 return;
6ec1f4e0 359
4077bf7a 360 result = (struct ptr_data *)
c1f445d2 361 saving_htab->find_with_hash (*ptr, POINTER_HASH (*ptr));
0d59b19d 362 gcc_assert (result);
573aba85 363 *ptr = result->new_addr;
364}
365
366/* Write out, after relocation, the pointers in TAB. */
367static void
6ec1f4e0 368write_pch_globals (const struct ggc_root_tab * const *tab,
369 struct traversal_state *state)
573aba85 370{
371 const struct ggc_root_tab *const *rt;
372 const struct ggc_root_tab *rti;
373 size_t i;
374
375 for (rt = tab; *rt; rt++)
376 for (rti = *rt; rti->base != NULL; rti++)
377 for (i = 0; i < rti->nelt; i++)
378 {
379 void *ptr = *(void **)((char *)rti->base + rti->stride * i);
380 struct ptr_data *new_ptr;
381 if (ptr == NULL || ptr == (void *)1)
382 {
6ec1f4e0 383 if (fwrite (&ptr, sizeof (void *), 1, state->f)
573aba85 384 != 1)
85b9be9b 385 fatal_error (input_location, "cannot write PCH file: %m");
573aba85 386 }
387 else
388 {
4077bf7a 389 new_ptr = (struct ptr_data *)
c1f445d2 390 saving_htab->find_with_hash (ptr, POINTER_HASH (ptr));
6ec1f4e0 391 if (fwrite (&new_ptr->new_addr, sizeof (void *), 1, state->f)
573aba85 392 != 1)
85b9be9b 393 fatal_error (input_location, "cannot write PCH file: %m");
573aba85 394 }
395 }
396}
397
398/* Hold the information we need to mmap the file back in. */
399
6ec1f4e0 400struct mmap_info
573aba85 401{
402 size_t offset;
403 size_t size;
404 void *preferred_base;
405};
406
407/* Write out the state of the compiler to F. */
408
409void
6ec1f4e0 410gt_pch_save (FILE *f)
573aba85 411{
412 const struct ggc_root_tab *const *rt;
413 const struct ggc_root_tab *rti;
414 size_t i;
415 struct traversal_state state;
416 char *this_object = NULL;
417 size_t this_object_size = 0;
418 struct mmap_info mmi;
9af5ce0c 419 const size_t mmap_offset_alignment = host_hooks.gt_pch_alloc_granularity ();
573aba85 420
421 gt_pch_save_stringpool ();
422
dbb19e66 423 timevar_push (TV_PCH_PTR_REALLOC);
c1f445d2 424 saving_htab = new hash_table<saving_hasher> (50000);
573aba85 425
426 for (rt = gt_ggc_rtab; *rt; rt++)
427 for (rti = *rt; rti->base != NULL; rti++)
428 for (i = 0; i < rti->nelt; i++)
429 (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
430
573aba85 431 /* Prepare the objects for writing, determine addresses and such. */
432 state.f = f;
ba72912a 433 state.d = init_ggc_pch ();
573aba85 434 state.count = 0;
c1f445d2 435 saving_htab->traverse <traversal_state *, ggc_call_count> (&state);
573aba85 436
437 mmi.size = ggc_pch_total_size (state.d);
438
ddf4604f 439 /* Try to arrange things so that no relocation is necessary, but
440 don't try very hard. On most platforms, this will always work,
48e1416a 441 and on the rest it's a lot of work to do better.
ddf4604f 442 (The extra work goes in HOST_HOOKS_GT_PCH_GET_ADDRESS and
443 HOST_HOOKS_GT_PCH_USE_ADDRESS.) */
53ee4dac 444 mmi.preferred_base = host_hooks.gt_pch_get_address (mmi.size, fileno (f));
48e1416a 445
573aba85 446 ggc_pch_this_base (state.d, mmi.preferred_base);
447
4c36ffe6 448 state.ptrs = XNEWVEC (struct ptr_data *, state.count);
573aba85 449 state.ptrs_i = 0;
dbb19e66 450
c1f445d2 451 saving_htab->traverse <traversal_state *, ggc_call_alloc> (&state);
dbb19e66 452 timevar_pop (TV_PCH_PTR_REALLOC);
453
454 timevar_push (TV_PCH_PTR_SORT);
573aba85 455 qsort (state.ptrs, state.count, sizeof (*state.ptrs), compare_ptr_data);
dbb19e66 456 timevar_pop (TV_PCH_PTR_SORT);
573aba85 457
458 /* Write out all the scalar variables. */
459 for (rt = gt_pch_scalar_rtab; *rt; rt++)
460 for (rti = *rt; rti->base != NULL; rti++)
461 if (fwrite (rti->base, rti->stride, 1, f) != 1)
85b9be9b 462 fatal_error (input_location, "cannot write PCH file: %m");
573aba85 463
464 /* Write out all the global pointers, after translation. */
465 write_pch_globals (gt_ggc_rtab, &state);
573aba85 466
62b4d90e 467 /* Pad the PCH file so that the mmapped area starts on an allocation
468 granularity (usually page) boundary. */
573aba85 469 {
04ea9445 470 long o;
471 o = ftell (state.f) + sizeof (mmi);
472 if (o == -1)
85b9be9b 473 fatal_error (input_location, "cannot get position in PCH file: %m");
62b4d90e 474 mmi.offset = mmap_offset_alignment - o % mmap_offset_alignment;
475 if (mmi.offset == mmap_offset_alignment)
573aba85 476 mmi.offset = 0;
477 mmi.offset += o;
478 }
479 if (fwrite (&mmi, sizeof (mmi), 1, state.f) != 1)
85b9be9b 480 fatal_error (input_location, "cannot write PCH file: %m");
573aba85 481 if (mmi.offset != 0
482 && fseek (state.f, mmi.offset, SEEK_SET) != 0)
85b9be9b 483 fatal_error (input_location, "cannot write padding to PCH file: %m");
573aba85 484
1bb42c87 485 ggc_pch_prepare_write (state.d, state.f);
486
badce224 487#if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
5ceebb21 488 vec<char> vbits = vNULL;
489#endif
490
573aba85 491 /* Actually write out the objects. */
492 for (i = 0; i < state.count; i++)
4e00b6fd 493 {
573aba85 494 if (this_object_size < state.ptrs[i]->size)
495 {
496 this_object_size = state.ptrs[i]->size;
4077bf7a 497 this_object = XRESIZEVAR (char, this_object, this_object_size);
573aba85 498 }
badce224 499#if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
5ceebb21 500 /* obj might contain uninitialized bytes, e.g. in the trailing
501 padding of the object. Avoid warnings by making the memory
502 temporarily defined and then restoring previous state. */
503 int get_vbits = 0;
504 size_t valid_size = state.ptrs[i]->size;
505 if (__builtin_expect (RUNNING_ON_VALGRIND, 0))
506 {
507 if (vbits.length () < valid_size)
508 vbits.safe_grow (valid_size);
509 get_vbits = VALGRIND_GET_VBITS (state.ptrs[i]->obj,
510 vbits.address (), valid_size);
511 if (get_vbits == 3)
512 {
513 /* We assume that first part of obj is addressable, and
514 the rest is unaddressable. Find out where the boundary is
515 using binary search. */
516 size_t lo = 0, hi = valid_size;
517 while (hi > lo)
518 {
519 size_t mid = (lo + hi) / 2;
520 get_vbits = VALGRIND_GET_VBITS ((char *) state.ptrs[i]->obj
521 + mid, vbits.address (),
522 1);
523 if (get_vbits == 3)
524 hi = mid;
525 else if (get_vbits == 1)
526 lo = mid + 1;
527 else
528 break;
529 }
530 if (get_vbits == 1 || get_vbits == 3)
531 {
532 valid_size = lo;
533 get_vbits = VALGRIND_GET_VBITS (state.ptrs[i]->obj,
534 vbits.address (),
535 valid_size);
536 }
537 }
538 if (get_vbits == 1)
539 VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (state.ptrs[i]->obj,
540 state.ptrs[i]->size));
541 }
542#endif
573aba85 543 memcpy (this_object, state.ptrs[i]->obj, state.ptrs[i]->size);
544 if (state.ptrs[i]->reorder_fn != NULL)
6ec1f4e0 545 state.ptrs[i]->reorder_fn (state.ptrs[i]->obj,
573aba85 546 state.ptrs[i]->note_ptr_cookie,
547 relocate_ptrs, &state);
6ec1f4e0 548 state.ptrs[i]->note_ptr_fn (state.ptrs[i]->obj,
573aba85 549 state.ptrs[i]->note_ptr_cookie,
550 relocate_ptrs, &state);
551 ggc_pch_write_object (state.d, state.f, state.ptrs[i]->obj,
53ee4dac 552 state.ptrs[i]->new_addr, state.ptrs[i]->size,
553 state.ptrs[i]->note_ptr_fn == gt_pch_p_S);
573aba85 554 if (state.ptrs[i]->note_ptr_fn != gt_pch_p_S)
555 memcpy (state.ptrs[i]->obj, this_object, state.ptrs[i]->size);
badce224 556#if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
5ceebb21 557 if (__builtin_expect (get_vbits == 1, 0))
558 {
559 (void) VALGRIND_SET_VBITS (state.ptrs[i]->obj, vbits.address (),
560 valid_size);
561 if (valid_size != state.ptrs[i]->size)
562 VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *)
563 state.ptrs[i]->obj
564 + valid_size,
565 state.ptrs[i]->size
566 - valid_size));
567 }
568#endif
4e00b6fd 569 }
badce224 570#if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
5ceebb21 571 vbits.release ();
572#endif
573
573aba85 574 ggc_pch_finish (state.d, state.f);
78e9fc50 575 gt_pch_fixup_stringpool ();
573aba85 576
5ceebb21 577 XDELETE (state.ptrs);
578 XDELETE (this_object);
c1f445d2 579 delete saving_htab;
580 saving_htab = NULL;
573aba85 581}
582
583/* Read the state of the compiler back in from F. */
584
585void
6ec1f4e0 586gt_pch_restore (FILE *f)
573aba85 587{
588 const struct ggc_root_tab *const *rt;
589 const struct ggc_root_tab *rti;
590 size_t i;
591 struct mmap_info mmi;
53ee4dac 592 int result;
573aba85 593
594 /* Delete any deletable objects. This makes ggc_pch_read much
595 faster, as it can be sure that no GCable objects remain other
596 than the ones just read in. */
597 for (rt = gt_ggc_deletable_rtab; *rt; rt++)
598 for (rti = *rt; rti->base != NULL; rti++)
599 memset (rti->base, 0, rti->stride);
600
601 /* Read in all the scalar variables. */
602 for (rt = gt_pch_scalar_rtab; *rt; rt++)
603 for (rti = *rt; rti->base != NULL; rti++)
604 if (fread (rti->base, rti->stride, 1, f) != 1)
85b9be9b 605 fatal_error (input_location, "cannot read PCH file: %m");
573aba85 606
607 /* Read in all the global pointers, in 6 easy loops. */
608 for (rt = gt_ggc_rtab; *rt; rt++)
609 for (rti = *rt; rti->base != NULL; rti++)
610 for (i = 0; i < rti->nelt; i++)
611 if (fread ((char *)rti->base + rti->stride * i,
612 sizeof (void *), 1, f) != 1)
85b9be9b 613 fatal_error (input_location, "cannot read PCH file: %m");
573aba85 614
573aba85 615 if (fread (&mmi, sizeof (mmi), 1, f) != 1)
85b9be9b 616 fatal_error (input_location, "cannot read PCH file: %m");
6ec1f4e0 617
53ee4dac 618 result = host_hooks.gt_pch_use_address (mmi.preferred_base, mmi.size,
619 fileno (f), mmi.offset);
620 if (result < 0)
c05be867 621 fatal_error (input_location, "had to relocate PCH");
53ee4dac 622 if (result == 0)
ddf4604f 623 {
53ee4dac 624 if (fseek (f, mmi.offset, SEEK_SET) != 0
625 || fread (mmi.preferred_base, mmi.size, 1, f) != 1)
85b9be9b 626 fatal_error (input_location, "cannot read PCH file: %m");
53ee4dac 627 }
628 else if (fseek (f, mmi.offset + mmi.size, SEEK_SET) != 0)
85b9be9b 629 fatal_error (input_location, "cannot read PCH file: %m");
605921ec 630
53ee4dac 631 ggc_pch_read (f, mmi.preferred_base);
ddf4604f 632
53ee4dac 633 gt_pch_restore_stringpool ();
634}
ddf4604f 635
53ee4dac 636/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is not present.
637 Select no address whatsoever, and let gt_pch_save choose what it will with
638 malloc, presumably. */
48443f83 639
53ee4dac 640void *
641default_gt_pch_get_address (size_t size ATTRIBUTE_UNUSED,
642 int fd ATTRIBUTE_UNUSED)
643{
644 return NULL;
645}
48443f83 646
53ee4dac 647/* Default version of HOST_HOOKS_GT_PCH_USE_ADDRESS when mmap is not present.
648 Allocate SIZE bytes with malloc. Return 0 if the address we got is the
649 same as base, indicating that the memory has been allocated but needs to
650 be read in from the file. Return -1 if the address differs, to relocation
651 of the PCH file would be required. */
652
653int
654default_gt_pch_use_address (void *base, size_t size, int fd ATTRIBUTE_UNUSED,
655 size_t offset ATTRIBUTE_UNUSED)
656{
657 void *addr = xmalloc (size);
658 return (addr == base) - 1;
659}
48443f83 660
62b4d90e 661/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS. Return the
662 alignment required for allocating virtual memory. Usually this is the
663 same as pagesize. */
664
665size_t
666default_gt_pch_alloc_granularity (void)
667{
9af5ce0c 668 return getpagesize ();
62b4d90e 669}
670
53ee4dac 671#if HAVE_MMAP_FILE
672/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is present.
673 We temporarily allocate SIZE bytes, and let the kernel place the data
3927afe0 674 wherever it will. If it worked, that's our spot, if not we're likely
53ee4dac 675 to be in trouble. */
605921ec 676
53ee4dac 677void *
678mmap_gt_pch_get_address (size_t size, int fd)
679{
680 void *ret;
ddf4604f 681
53ee4dac 682 ret = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
683 if (ret == (void *) MAP_FAILED)
684 ret = NULL;
685 else
1d5a5c71 686 munmap ((caddr_t) ret, size);
4e00b6fd 687
53ee4dac 688 return ret;
689}
4e00b6fd 690
53ee4dac 691/* Default version of HOST_HOOKS_GT_PCH_USE_ADDRESS when mmap is present.
48e1416a 692 Map SIZE bytes of FD+OFFSET at BASE. Return 1 if we succeeded at
53ee4dac 693 mapping the data at BASE, -1 if we couldn't.
6ec1f4e0 694
53ee4dac 695 This version assumes that the kernel honors the START operand of mmap
696 even without MAP_FIXED if START through START+SIZE are not currently
697 mapped with something. */
573aba85 698
53ee4dac 699int
700mmap_gt_pch_use_address (void *base, size_t size, int fd, size_t offset)
701{
702 void *addr;
573aba85 703
53ee4dac 704 /* We're called with size == 0 if we're not planning to load a PCH
705 file at all. This allows the hook to free any static space that
706 we might have allocated at link time. */
707 if (size == 0)
708 return -1;
709
1d5a5c71 710 addr = mmap ((caddr_t) base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
53ee4dac 711 fd, offset);
712
713 return addr == base ? 1 : -1;
4e00b6fd 714}
53ee4dac 715#endif /* HAVE_MMAP_FILE */
7d83df95 716
9ca7413c 717#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
718
4cb2b0dd 719/* Modify the bound based on rlimits. */
2577ed5c 720static double
6ec1f4e0 721ggc_rlimit_bound (double limit)
2577ed5c 722{
723#if defined(HAVE_GETRLIMIT)
724 struct rlimit rlim;
4cb2b0dd 725# if defined (RLIMIT_AS)
726 /* RLIMIT_AS is what POSIX says is the limit on mmap. Presumably
727 any OS which has RLIMIT_AS also has a working mmap that GCC will use. */
728 if (getrlimit (RLIMIT_AS, &rlim) == 0
26106956 729 && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
2577ed5c 730 && rlim.rlim_cur < limit)
731 limit = rlim.rlim_cur;
4cb2b0dd 732# elif defined (RLIMIT_DATA)
733 /* ... but some older OSs bound mmap based on RLIMIT_DATA, or we
734 might be on an OS that has a broken mmap. (Others don't bound
735 mmap at all, apparently.) */
2577ed5c 736 if (getrlimit (RLIMIT_DATA, &rlim) == 0
26106956 737 && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
4cb2b0dd 738 && rlim.rlim_cur < limit
739 /* Darwin has this horribly bogus default setting of
740 RLIMIT_DATA, to 6144Kb. No-one notices because RLIMIT_DATA
741 appears to be ignored. Ignore such silliness. If a limit
742 this small was actually effective for mmap, GCC wouldn't even
743 start up. */
744 && rlim.rlim_cur >= 8 * 1024 * 1024)
2577ed5c 745 limit = rlim.rlim_cur;
4cb2b0dd 746# endif /* RLIMIT_AS or RLIMIT_DATA */
2577ed5c 747#endif /* HAVE_GETRLIMIT */
748
749 return limit;
750}
751
7d83df95 752/* Heuristic to set a default for GGC_MIN_EXPAND. */
9ca7413c 753static int
6ec1f4e0 754ggc_min_expand_heuristic (void)
7d83df95 755{
9af5ce0c 756 double min_expand = physmem_total ();
2577ed5c 757
758 /* Adjust for rlimits. */
759 min_expand = ggc_rlimit_bound (min_expand);
6ec1f4e0 760
7d83df95 761 /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding
762 a lower bound of 30% and an upper bound of 100% (when RAM >= 1GB). */
763 min_expand /= 1024*1024*1024;
764 min_expand *= 70;
765 min_expand = MIN (min_expand, 70);
766 min_expand += 30;
767
768 return min_expand;
769}
770
771/* Heuristic to set a default for GGC_MIN_HEAPSIZE. */
9ca7413c 772static int
6ec1f4e0 773ggc_min_heapsize_heuristic (void)
7d83df95 774{
9af5ce0c 775 double phys_kbytes = physmem_total ();
4cb2b0dd 776 double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2);
2577ed5c 777
4cb2b0dd 778 phys_kbytes /= 1024; /* Convert to Kbytes. */
779 limit_kbytes /= 1024;
6ec1f4e0 780
7d83df95 781 /* The heuristic is RAM/8, with a lower bound of 4M and an upper
782 bound of 128M (when RAM >= 1GB). */
4cb2b0dd 783 phys_kbytes /= 8;
784
785#if defined(HAVE_GETRLIMIT) && defined (RLIMIT_RSS)
48e1416a 786 /* Try not to overrun the RSS limit while doing garbage collection.
4cb2b0dd 787 The RSS limit is only advisory, so no margin is subtracted. */
788 {
789 struct rlimit rlim;
790 if (getrlimit (RLIMIT_RSS, &rlim) == 0
791 && rlim.rlim_cur != (rlim_t) RLIM_INFINITY)
792 phys_kbytes = MIN (phys_kbytes, rlim.rlim_cur / 1024);
793 }
794# endif
795
796 /* Don't blindly run over our data limit; do GC at least when the
3a1e1e08 797 *next* GC would be within 20Mb of the limit or within a quarter of
798 the limit, whichever is larger. If GCC does hit the data limit,
799 compilation will fail, so this tries to be conservative. */
800 limit_kbytes = MAX (0, limit_kbytes - MAX (limit_kbytes / 4, 20 * 1024));
ba72912a 801 limit_kbytes = (limit_kbytes * 100) / (110 + ggc_min_expand_heuristic ());
4cb2b0dd 802 phys_kbytes = MIN (phys_kbytes, limit_kbytes);
803
804 phys_kbytes = MAX (phys_kbytes, 4 * 1024);
805 phys_kbytes = MIN (phys_kbytes, 128 * 1024);
7d83df95 806
4cb2b0dd 807 return phys_kbytes;
7d83df95 808}
9ca7413c 809#endif
7d83df95 810
811void
6ec1f4e0 812init_ggc_heuristics (void)
7d83df95 813{
55074432 814#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
686e2769 815 set_default_param_value (GGC_MIN_EXPAND, ggc_min_expand_heuristic ());
816 set_default_param_value (GGC_MIN_HEAPSIZE, ggc_min_heapsize_heuristic ());
7d83df95 817#endif
818}
674b05f5 819
0ff42de5 820/* GGC memory usage. */
251317e4 821class ggc_usage: public mem_usage
674b05f5 822{
251317e4 823public:
0ff42de5 824 /* Default constructor. */
825 ggc_usage (): m_freed (0), m_collected (0), m_overhead (0) {}
826 /* Constructor. */
827 ggc_usage (size_t allocated, size_t times, size_t peak,
828 size_t freed, size_t collected, size_t overhead)
829 : mem_usage (allocated, times, peak),
830 m_freed (freed), m_collected (collected), m_overhead (overhead) {}
674b05f5 831
267c6bca 832 /* Equality operator. */
833 inline bool
834 operator== (const ggc_usage &second) const
835 {
836 return (get_balance () == second.get_balance ()
837 && m_peak == second.m_peak
838 && m_times == second.m_times);
839 }
840
0ff42de5 841 /* Comparison operator. */
94302dfa 842 inline bool
843 operator< (const ggc_usage &second) const
0ff42de5 844 {
267c6bca 845 if (*this == second)
846 return false;
847
0ff42de5 848 return (get_balance () == second.get_balance () ?
849 (m_peak == second.m_peak ? m_times < second.m_times
850 : m_peak < second.m_peak)
851 : get_balance () < second.get_balance ());
852 }
674b05f5 853
0ff42de5 854 /* Register overhead of ALLOCATED and OVERHEAD bytes. */
94302dfa 855 inline void
856 register_overhead (size_t allocated, size_t overhead)
0ff42de5 857 {
858 m_allocated += allocated;
859 m_overhead += overhead;
860 m_times++;
861 }
674b05f5 862
0ff42de5 863 /* Release overhead of SIZE bytes. */
94302dfa 864 inline void
865 release_overhead (size_t size)
0ff42de5 866 {
867 m_freed += size;
868 }
674b05f5 869
0ff42de5 870 /* Sum the usage with SECOND usage. */
94302dfa 871 ggc_usage
872 operator+ (const ggc_usage &second)
0ff42de5 873 {
874 return ggc_usage (m_allocated + second.m_allocated,
875 m_times + second.m_times,
876 m_peak + second.m_peak,
877 m_freed + second.m_freed,
878 m_collected + second.m_collected,
879 m_overhead + second.m_overhead);
880 }
674b05f5 881
0ff42de5 882 /* Dump usage with PREFIX, where TOTAL is sum of all rows. */
94302dfa 883 inline void
884 dump (const char *prefix, ggc_usage &total) const
0ff42de5 885 {
7a413494 886 size_t balance = get_balance ();
0ff42de5 887 fprintf (stderr,
03fac02c 888 "%-48s " PRsa (9) ":%5.1f%%" PRsa (9) ":%5.1f%%"
889 PRsa (9) ":%5.1f%%" PRsa (9) ":%5.1f%%" PRsa (9) "\n",
7a413494 890 prefix, SIZE_AMOUNT (m_collected),
0ff42de5 891 get_percent (m_collected, total.m_collected),
7a413494 892 SIZE_AMOUNT (m_freed), get_percent (m_freed, total.m_freed),
893 SIZE_AMOUNT (balance), get_percent (balance, total.get_balance ()),
894 SIZE_AMOUNT (m_overhead),
895 get_percent (m_overhead, total.m_overhead),
896 SIZE_AMOUNT (m_times));
0ff42de5 897 }
d9dd21a8 898
0ff42de5 899 /* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */
94302dfa 900 inline void
901 dump (mem_location *loc, ggc_usage &total) const
0ff42de5 902 {
7da284df 903 char *location_string = loc->to_string ();
0ca9a7b6 904
7da284df 905 dump (location_string, total);
906
907 free (location_string);
0ff42de5 908 }
d9dd21a8 909
0ff42de5 910 /* Dump footer. */
94302dfa 911 inline void
912 dump_footer ()
0ff42de5 913 {
0ff42de5 914 dump ("Total", *this);
0ff42de5 915 }
0ca9a7b6 916
0ff42de5 917 /* Get balance which is GGC allocation leak. */
7a413494 918 inline size_t
94302dfa 919 get_balance () const
0ff42de5 920 {
921 return m_allocated + m_overhead - m_collected - m_freed;
922 }
0ca9a7b6 923
0ff42de5 924 typedef std::pair<mem_location *, ggc_usage *> mem_pair_t;
0ca9a7b6 925
0ff42de5 926 /* Compare wrapper used by qsort method. */
94302dfa 927 static int
928 compare (const void *first, const void *second)
0ff42de5 929 {
930 const mem_pair_t f = *(const mem_pair_t *)first;
931 const mem_pair_t s = *(const mem_pair_t *)second;
d9dd21a8 932
7a413494 933 return s.second->get_balance () - f.second->get_balance ();
0ff42de5 934 }
935
936 /* Compare rows in final GGC summary dump. */
94302dfa 937 static int
938 compare_final (const void *first, const void *second)
939 {
940 typedef std::pair<mem_location *, ggc_usage *> mem_pair_t;
0ff42de5 941
942 const ggc_usage *f = ((const mem_pair_t *)first)->second;
943 const ggc_usage *s = ((const mem_pair_t *)second)->second;
944
945 size_t a = f->m_allocated + f->m_overhead - f->m_freed;
946 size_t b = s->m_allocated + s->m_overhead - s->m_freed;
947
948 return a == b ? 0 : (a < b ? 1 : -1);
949 }
950
951 /* Dump header with NAME. */
94302dfa 952 static inline void
953 dump_header (const char *name)
0ff42de5 954 {
955 fprintf (stderr, "%-48s %11s%17s%17s%16s%17s\n", name, "Garbage", "Freed",
956 "Leak", "Overhead", "Times");
0ff42de5 957 }
958
959 /* Freed memory in bytes. */
960 size_t m_freed;
961 /* Collected memory in bytes. */
962 size_t m_collected;
963 /* Overhead memory in bytes. */
964 size_t m_overhead;
965};
966
967/* GCC memory description. */
968static mem_alloc_description<ggc_usage> ggc_mem_desc;
969
970/* Dump per-site memory statistics. */
674b05f5 971
3927afe0 972void
0ff42de5 973dump_ggc_loc_statistics (bool final)
674b05f5 974{
0ff42de5 975 if (! GATHER_STATISTICS)
976 return;
674b05f5 977
0ff42de5 978 ggc_force_collect = true;
979 ggc_collect ();
980
a80feb6c 981 ggc_mem_desc.dump (GGC_ORIGIN, final ? ggc_usage::compare_final : NULL);
0ff42de5 982
983 ggc_force_collect = false;
0ca9a7b6 984}
985
0ff42de5 986/* Record ALLOCATED and OVERHEAD bytes to descriptor NAME:LINE (FUNCTION). */
0ca9a7b6 987void
0ff42de5 988ggc_record_overhead (size_t allocated, size_t overhead, void *ptr MEM_STAT_DECL)
0ca9a7b6 989{
a80feb6c 990 ggc_usage *usage = ggc_mem_desc.register_descriptor (ptr, GGC_ORIGIN, false
0ff42de5 991 FINAL_PASS_MEM_STAT);
992
993 ggc_mem_desc.register_object_overhead (usage, allocated + overhead, ptr);
994 usage->register_overhead (allocated, overhead);
0ca9a7b6 995}
996
997/* Notice that the pointer has been freed. */
2e2fd8fe 998void
999ggc_free_overhead (void *ptr)
0ca9a7b6 1000{
0ff42de5 1001 ggc_mem_desc.release_object_overhead (ptr);
51949610 1002}
1003
0ff42de5 1004/* After live values has been marked, walk all recorded pointers and see if
1005 they are still live. */
2e2fd8fe 1006void
0ff42de5 1007ggc_prune_overhead_list (void)
674b05f5 1008{
0ff42de5 1009 typedef hash_map<const void *, std::pair<ggc_usage *, size_t > > map_t;
674b05f5 1010
0ff42de5 1011 map_t::iterator it = ggc_mem_desc.m_reverse_object_map->begin ();
ecd52ea9 1012
0ff42de5 1013 for (; it != ggc_mem_desc.m_reverse_object_map->end (); ++it)
1014 if (!ggc_marked_p ((*it).first))
1015 (*it).second.first->m_collected += (*it).second.second;
0ca9a7b6 1016
0ff42de5 1017 delete ggc_mem_desc.m_reverse_object_map;
163a5418 1018 ggc_mem_desc.m_reverse_object_map = new map_t (13, false, false, false);
674b05f5 1019}