Branch data Line data Source code
1 : : /* Simple garbage collection for the GNU compiler.
2 : : Copyright (C) 1999-2025 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify it under
7 : : the terms of the GNU General Public License as published by the Free
8 : : Software Foundation; either version 3, or (at your option) any later
9 : : version.
10 : :
11 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : : for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : /* Generic garbage collection (GC) functions and data, not specific to
21 : : any particular GC implementation. */
22 : :
23 : : #include "config.h"
24 : : #define INCLUDE_MALLOC_H
25 : : #include "system.h"
26 : : #include "coretypes.h"
27 : : #include "timevar.h"
28 : : #include "diagnostic-core.h"
29 : : #include "ggc-internal.h"
30 : : #include "hosthooks.h"
31 : : #include "plugin.h"
32 : : #include "options.h"
33 : :
34 : : /* When true, protect the contents of the identifier hash table. */
35 : : bool ggc_protect_identifiers = true;
36 : :
37 : : /* Statistics about the allocation. */
38 : : static ggc_statistics *ggc_stats;
39 : :
40 : : struct traversal_state;
41 : :
42 : : static int compare_ptr_data (const void *, const void *);
43 : : static void relocate_ptrs (void *, void *, void *);
44 : : static void write_pch_globals (const struct ggc_root_tab * const *tab,
45 : : struct traversal_state *state);
46 : :
47 : : /* Maintain global roots that are preserved during GC. */
48 : :
49 : : /* This extra vector of dynamically registered root_tab-s is used by
50 : : ggc_mark_roots and gives the ability to dynamically add new GGC root
51 : : tables, for instance from some plugins; this vector is on the heap
52 : : since it is used by GGC internally. */
53 : : typedef const struct ggc_root_tab *const_ggc_root_tab_t;
54 : : static vec<const_ggc_root_tab_t> extra_root_vec;
55 : :
56 : : /* Dynamically register a new GGC root table RT. This is useful for
57 : : plugins. */
58 : :
59 : : void
60 : 124 : ggc_register_root_tab (const struct ggc_root_tab* rt)
61 : : {
62 : 124 : if (rt)
63 : 124 : extra_root_vec.safe_push (rt);
64 : 124 : }
65 : :
66 : : /* Mark all the roots in the table RT. */
67 : :
68 : : static void
69 : 39615278 : ggc_mark_root_tab (const_ggc_root_tab_t rt)
70 : : {
71 : 39615278 : size_t i;
72 : :
73 : 283931925 : for ( ; rt->base != NULL; rt++)
74 : 6802509316 : for (i = 0; i < rt->nelt; i++)
75 : 6558192669 : (*rt->cb) (*(void **) ((char *)rt->base + rt->stride * i));
76 : 39615278 : }
77 : :
78 : : /* Zero out all the roots in the table RT. */
79 : :
80 : : static void
81 : 16312838 : ggc_zero_rtab_roots (const_ggc_root_tab_t rt)
82 : : {
83 : 16312838 : size_t i;
84 : :
85 : 119117824 : for ( ; rt->base != NULL; rt++)
86 : 2620641656 : for (i = 0; i < rt->nelt; i++)
87 : 2517836670 : (*(void **) ((char *)rt->base + rt->stride * i)) = (void*)0;
88 : 16312838 : }
89 : :
90 : : /* Iterate through all registered roots and mark each element. */
91 : :
92 : : void
93 : 696229 : ggc_mark_roots (void)
94 : : {
95 : 696229 : const struct ggc_root_tab *const *rt;
96 : 696229 : const_ggc_root_tab_t rtp, rti;
97 : 696229 : size_t i;
98 : :
99 : 7648953 : for (rt = gt_ggc_deletable_rtab; *rt; rt++)
100 : 16605996 : for (rti = *rt; rti->base != NULL; rti++)
101 : 9653272 : memset (rti->base, 0, rti->stride * rti->nelt);
102 : :
103 : 39812477 : for (rt = gt_ggc_rtab; *rt; rt++)
104 : 39116248 : ggc_mark_root_tab (*rt);
105 : :
106 : 1195259 : FOR_EACH_VEC_ELT (extra_root_vec, i, rtp)
107 : 499030 : ggc_mark_root_tab (rtp);
108 : :
109 : 696229 : if (ggc_protect_identifiers)
110 : 149085 : ggc_mark_stringpool ();
111 : :
112 : 696229 : gt_clear_caches ();
113 : :
114 : 696229 : if (! ggc_protect_identifiers)
115 : 547144 : ggc_purge_stringpool ();
116 : :
117 : : /* Some plugins may call ggc_set_mark from here. */
118 : 696229 : invoke_plugin_callbacks (PLUGIN_GGC_MARKING, NULL);
119 : 696229 : }
120 : :
121 : : /* Allocate a block of memory, then clear it. */
122 : : #ifdef HAVE_ATTRIBUTE_ALIAS
123 : : extern "C" void *
124 : 18593043485 : ggc_internal_cleared_alloc_ (size_t size, void (*f)(void *), size_t s, size_t n
125 : : MEM_STAT_DECL)
126 : : {
127 : 18593043485 : void *buf = ggc_internal_alloc (size, f, s, n PASS_MEM_STAT);
128 : 18593043485 : memset (buf, 0, size);
129 : 18593043485 : return buf;
130 : : }
131 : :
132 : : extern void *
133 : : ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t s,
134 : : size_t n MEM_STAT_DECL)
135 : : __attribute__((__alias__ ("ggc_internal_cleared_alloc_")));
136 : : extern void *
137 : : ggc_internal_cleared_alloc_no_dtor (size_t size, void (*f)(void *),
138 : : size_t s, size_t n MEM_STAT_DECL)
139 : : __attribute__((__alias__ ("ggc_internal_cleared_alloc_")));
140 : : #else
141 : : void *
142 : : ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t s, size_t n
143 : : MEM_STAT_DECL)
144 : : {
145 : : void *buf = ggc_internal_alloc (size, f, s, n PASS_MEM_STAT);
146 : : memset (buf, 0, size);
147 : : return buf;
148 : : }
149 : :
150 : : #ifdef __GNUC__
151 : : __attribute__ ((__noinline__))
152 : : #endif
153 : : void *
154 : : ggc_internal_cleared_alloc_no_dtor (size_t size, void (*f)(void *),
155 : : size_t s, size_t n MEM_STAT_DECL)
156 : : {
157 : : return ggc_internal_cleared_alloc (size, f, s, n PASS_MEM_STAT);
158 : : }
159 : : #endif
160 : :
161 : : /* Resize a block of memory, possibly re-allocating it. */
162 : : void *
163 : 2854385002 : ggc_realloc (void *x, size_t size MEM_STAT_DECL)
164 : : {
165 : 2854385002 : void *r;
166 : 2854385002 : size_t old_size;
167 : :
168 : 2854385002 : if (x == NULL)
169 : 2422332677 : return ggc_internal_alloc (size PASS_MEM_STAT);
170 : :
171 : 432052325 : old_size = ggc_get_size (x);
172 : :
173 : 432052325 : if (size <= old_size)
174 : : {
175 : : /* Mark the unwanted memory as unaccessible. We also need to make
176 : : the "new" size accessible, since ggc_get_size returns the size of
177 : : the pool, not the size of the individually allocated object, the
178 : : size which was previously made accessible. Unfortunately, we
179 : : don't know that previously allocated size. Without that
180 : : knowledge we have to lose some initialization-tracking for the
181 : : old parts of the object. An alternative is to mark the whole
182 : : old_size as reachable, but that would lose tracking of writes
183 : : after the end of the object (by small offsets). Discard the
184 : : handle to avoid handle leak. */
185 : : VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *) x + size,
186 : : old_size - size));
187 : : VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (x, size));
188 : : return x;
189 : : }
190 : :
191 : 431551445 : r = ggc_internal_alloc (size PASS_MEM_STAT);
192 : :
193 : : /* Since ggc_get_size returns the size of the pool, not the size of the
194 : : individually allocated object, we'd access parts of the old object
195 : : that were marked invalid with the memcpy below. We lose a bit of the
196 : : initialization-tracking since some of it may be uninitialized. */
197 : 431551445 : VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (x, old_size));
198 : :
199 : 431551445 : memcpy (r, x, old_size);
200 : :
201 : : /* The old object is not supposed to be used anymore. */
202 : 431551445 : ggc_free (x);
203 : :
204 : 431551445 : return r;
205 : : }
206 : :
207 : : void *
208 : 0 : ggc_cleared_alloc_htab_ignore_args (size_t c ATTRIBUTE_UNUSED,
209 : : size_t n ATTRIBUTE_UNUSED)
210 : : {
211 : 0 : gcc_assert (c * n == sizeof (struct htab));
212 : 0 : return ggc_cleared_alloc<htab> ();
213 : : }
214 : :
215 : : /* TODO: once we actually use type information in GGC, create a new tag
216 : : gt_gcc_ptr_array and use it for pointer arrays. */
217 : : void *
218 : 0 : ggc_cleared_alloc_ptr_array_two_args (size_t c, size_t n)
219 : : {
220 : 0 : gcc_assert (sizeof (void **) == n);
221 : 0 : return ggc_cleared_vec_alloc<void **> (c);
222 : : }
223 : :
224 : : /* These are for splay_tree_new_ggc. */
225 : : void *
226 : 0 : ggc_splay_alloc (int sz, void *nl)
227 : : {
228 : 0 : gcc_assert (!nl);
229 : 0 : return ggc_internal_alloc (sz);
230 : : }
231 : :
232 : : void
233 : 0 : ggc_splay_dont_free (void * x ATTRIBUTE_UNUSED, void *nl)
234 : : {
235 : 0 : gcc_assert (!nl);
236 : 0 : }
237 : :
238 : : void
239 : 0 : ggc_print_common_statistics (FILE *stream ATTRIBUTE_UNUSED,
240 : : ggc_statistics *stats)
241 : : {
242 : : /* Set the pointer so that during collection we will actually gather
243 : : the statistics. */
244 : 0 : ggc_stats = stats;
245 : :
246 : : /* Then do one collection to fill in the statistics. */
247 : 0 : ggc_collect ();
248 : :
249 : : /* At present, we don't really gather any interesting statistics. */
250 : :
251 : : /* Don't gather statistics any more. */
252 : 0 : ggc_stats = NULL;
253 : 0 : }
254 : :
255 : : /* Functions for saving and restoring GCable memory to disk. */
256 : :
257 : : struct ptr_data
258 : : {
259 : : void *obj;
260 : : void *note_ptr_cookie;
261 : : gt_note_pointers note_ptr_fn;
262 : : gt_handle_reorder reorder_fn;
263 : : size_t size;
264 : : void *new_addr;
265 : : };
266 : :
267 : : #define POINTER_HASH(x) (hashval_t)((intptr_t)x >> 3)
268 : :
269 : : /* Helper for hashing saving_htab. */
270 : :
271 : : struct saving_hasher : free_ptr_hash <ptr_data>
272 : : {
273 : : typedef void *compare_type;
274 : : static inline hashval_t hash (const ptr_data *);
275 : : static inline bool equal (const ptr_data *, const void *);
276 : : };
277 : :
278 : : inline hashval_t
279 : 691284725 : saving_hasher::hash (const ptr_data *p)
280 : : {
281 : 691284725 : return POINTER_HASH (p->obj);
282 : : }
283 : :
284 : : inline bool
285 : 192059112 : saving_hasher::equal (const ptr_data *p1, const void *p2)
286 : : {
287 : 192059112 : return p1->obj == p2;
288 : : }
289 : :
290 : : static hash_table<saving_hasher> *saving_htab;
291 : : static vec<void *> callback_vec;
292 : : static vec<void *> reloc_addrs_vec;
293 : :
294 : : /* Register an object in the hash table. */
295 : :
296 : : int
297 : 87749251 : gt_pch_note_object (void *obj, void *note_ptr_cookie,
298 : : gt_note_pointers note_ptr_fn,
299 : : size_t length_override)
300 : : {
301 : 87749251 : struct ptr_data **slot;
302 : :
303 : 87749251 : if (obj == NULL || obj == (void *) 1)
304 : : return 0;
305 : :
306 : 74458826 : slot = (struct ptr_data **)
307 : 74458826 : saving_htab->find_slot_with_hash (obj, POINTER_HASH (obj), INSERT);
308 : 74458826 : if (*slot != NULL)
309 : : {
310 : 50112447 : gcc_assert ((*slot)->note_ptr_fn == note_ptr_fn
311 : : && (*slot)->note_ptr_cookie == note_ptr_cookie);
312 : : return 0;
313 : : }
314 : :
315 : 24346379 : *slot = XCNEW (struct ptr_data);
316 : 24346379 : (*slot)->obj = obj;
317 : 24346379 : (*slot)->note_ptr_fn = note_ptr_fn;
318 : 24346379 : (*slot)->note_ptr_cookie = note_ptr_cookie;
319 : 24346379 : if (length_override != (size_t)-1)
320 : 2109509 : (*slot)->size = length_override;
321 : 22236870 : else if (note_ptr_fn == gt_pch_p_S)
322 : 99178 : (*slot)->size = strlen ((const char *)obj) + 1;
323 : : else
324 : 22137692 : (*slot)->size = ggc_get_size (obj);
325 : : return 1;
326 : : }
327 : :
328 : : /* Register address of a callback pointer. */
329 : : void
330 : 4700 : gt_pch_note_callback (void *obj, void *base)
331 : : {
332 : 4700 : void *ptr;
333 : 4700 : memcpy (&ptr, obj, sizeof (void *));
334 : 4700 : if (ptr != NULL)
335 : : {
336 : 4700 : struct ptr_data *data
337 : : = (struct ptr_data *)
338 : 4700 : saving_htab->find_with_hash (base, POINTER_HASH (base));
339 : 4700 : gcc_assert (data);
340 : 4700 : callback_vec.safe_push ((char *) data->new_addr
341 : 4700 : + ((char *) obj - (char *) base));
342 : : }
343 : 4700 : }
344 : :
345 : : /* Register an object in the hash table. */
346 : :
347 : : void
348 : 87575 : gt_pch_note_reorder (void *obj, void *note_ptr_cookie,
349 : : gt_handle_reorder reorder_fn)
350 : : {
351 : 87575 : struct ptr_data *data;
352 : :
353 : 87575 : if (obj == NULL || obj == (void *) 1)
354 : : return;
355 : :
356 : 30534 : data = (struct ptr_data *)
357 : 15267 : saving_htab->find_with_hash (obj, POINTER_HASH (obj));
358 : 15267 : gcc_assert (data && data->note_ptr_cookie == note_ptr_cookie);
359 : : /* The GTY 'reorder' option doesn't make sense if we don't walk pointers,
360 : : such as for strings. */
361 : 15267 : gcc_checking_assert (data->note_ptr_fn != gt_pch_p_S);
362 : :
363 : 15267 : data->reorder_fn = reorder_fn;
364 : : }
365 : :
366 : : /* Handy state for the traversal functions. */
367 : :
368 : : struct traversal_state
369 : : {
370 : : FILE *f;
371 : : struct ggc_pch_data *d;
372 : : size_t count;
373 : : struct ptr_data **ptrs;
374 : : size_t ptrs_i;
375 : : };
376 : :
377 : : /* Callbacks for htab_traverse. */
378 : :
379 : : int
380 : 24346379 : ggc_call_count (ptr_data **slot, traversal_state *state)
381 : : {
382 : 24346379 : struct ptr_data *d = *slot;
383 : :
384 : 24346379 : ggc_pch_count_object (state->d, d->obj, d->size);
385 : 24346379 : state->count++;
386 : 24346379 : return 1;
387 : : }
388 : :
389 : : int
390 : 24346379 : ggc_call_alloc (ptr_data **slot, traversal_state *state)
391 : : {
392 : 24346379 : struct ptr_data *d = *slot;
393 : :
394 : 24346379 : d->new_addr = ggc_pch_alloc_object (state->d, d->obj, d->size);
395 : 24346379 : state->ptrs[state->ptrs_i++] = d;
396 : 24346379 : return 1;
397 : : }
398 : :
399 : : /* Callback for qsort. */
400 : :
401 : : static int
402 : 1762028050 : compare_ptr_data (const void *p1_p, const void *p2_p)
403 : : {
404 : 1762028050 : const struct ptr_data *const p1 = *(const struct ptr_data *const *)p1_p;
405 : 1762028050 : const struct ptr_data *const p2 = *(const struct ptr_data *const *)p2_p;
406 : 1762028050 : return (((size_t)p1->new_addr > (size_t)p2->new_addr)
407 : 1762028050 : - ((size_t)p1->new_addr < (size_t)p2->new_addr));
408 : : }
409 : :
410 : : /* Callbacks for note_ptr_fn. */
411 : :
412 : : static void
413 : 172331970 : relocate_ptrs (void *ptr_p, void *real_ptr_p, void *state_p)
414 : : {
415 : 172331970 : void **ptr = (void **)ptr_p;
416 : 172331970 : struct traversal_state *state
417 : : = (struct traversal_state *)state_p;
418 : 172331970 : struct ptr_data *result;
419 : :
420 : 172331970 : if (*ptr == NULL || *ptr == (void *)1)
421 : 107554646 : return;
422 : :
423 : 146980968 : result = (struct ptr_data *)
424 : 73490484 : saving_htab->find_with_hash (*ptr, POINTER_HASH (*ptr));
425 : 73490484 : gcc_assert (result);
426 : 73490484 : *ptr = result->new_addr;
427 : 73490484 : if (ptr_p == real_ptr_p)
428 : : return;
429 : 64777324 : if (real_ptr_p == NULL)
430 : 62218439 : real_ptr_p = ptr_p;
431 : 64777324 : gcc_assert (real_ptr_p >= state->ptrs[state->ptrs_i]->obj
432 : : && ((char *) real_ptr_p + sizeof (void *)
433 : : <= ((char *) state->ptrs[state->ptrs_i]->obj
434 : : + state->ptrs[state->ptrs_i]->size)));
435 : 64777324 : void *addr
436 : 64777324 : = (void *) ((char *) state->ptrs[state->ptrs_i]->new_addr
437 : : + ((char *) real_ptr_p
438 : 64777324 : - (char *) state->ptrs[state->ptrs_i]->obj));
439 : 64777324 : reloc_addrs_vec.safe_push (addr);
440 : : }
441 : :
442 : : /* Write out, after relocation, the pointers in TAB. */
443 : : static void
444 : 470 : write_pch_globals (const struct ggc_root_tab * const *tab,
445 : : struct traversal_state *state)
446 : : {
447 : 470 : const struct ggc_root_tab *const *rt;
448 : 470 : const struct ggc_root_tab *rti;
449 : 470 : size_t i;
450 : :
451 : 29516 : for (rt = tab; *rt; rt++)
452 : 206424 : for (rti = *rt; rti->base != NULL; rti++)
453 : 4751230 : for (i = 0; i < rti->nelt; i++)
454 : : {
455 : 4573852 : void *ptr = *(void **)((char *)rti->base + rti->stride * i);
456 : 4573852 : struct ptr_data *new_ptr;
457 : 4573852 : if (ptr == NULL || ptr == (void *)1)
458 : : {
459 : 3002696 : if (fwrite (&ptr, sizeof (void *), 1, state->f)
460 : : != 1)
461 : 0 : fatal_error (input_location, "cannot write PCH file: %m");
462 : : }
463 : : else
464 : : {
465 : 3142312 : new_ptr = (struct ptr_data *)
466 : 1571156 : saving_htab->find_with_hash (ptr, POINTER_HASH (ptr));
467 : 1571156 : if (fwrite (&new_ptr->new_addr, sizeof (void *), 1, state->f)
468 : : != 1)
469 : 0 : fatal_error (input_location, "cannot write PCH file: %m");
470 : : }
471 : : }
472 : 470 : }
473 : :
474 : : /* Callback for qsort. */
475 : :
476 : : static int
477 : 3944833238 : compare_ptr (const void *p1_p, const void *p2_p)
478 : : {
479 : 3944833238 : void *p1 = *(void *const *)p1_p;
480 : 3944833238 : void *p2 = *(void *const *)p2_p;
481 : 3944833238 : return (((uintptr_t)p1 > (uintptr_t)p2)
482 : 3944833238 : - ((uintptr_t)p1 < (uintptr_t)p2));
483 : : }
484 : :
485 : : /* Decode one uleb128 from P, return first byte after it, store
486 : : decoded value into *VAL. */
487 : :
488 : : static unsigned char *
489 : 0 : read_uleb128 (unsigned char *p, size_t *val)
490 : : {
491 : 0 : unsigned int shift = 0;
492 : 0 : unsigned char byte;
493 : 0 : size_t result;
494 : :
495 : 0 : result = 0;
496 : 0 : do
497 : : {
498 : 0 : byte = *p++;
499 : 0 : result |= ((size_t) byte & 0x7f) << shift;
500 : 0 : shift += 7;
501 : : }
502 : 0 : while (byte & 0x80);
503 : :
504 : 0 : *val = result;
505 : 0 : return p;
506 : : }
507 : :
508 : : /* Store VAL as uleb128 at P, return length in bytes. */
509 : :
510 : : static size_t
511 : 129554648 : write_uleb128 (unsigned char *p, size_t val)
512 : : {
513 : 0 : size_t len = 0;
514 : 134250618 : do
515 : : {
516 : 134250618 : unsigned char byte = (val & 0x7f);
517 : 134250618 : val >>= 7;
518 : 134250618 : if (val != 0)
519 : : /* More bytes to follow. */
520 : 4695970 : byte |= 0x80;
521 : :
522 : 134250618 : *p++ = byte;
523 : 134250618 : ++len;
524 : : }
525 : 134250618 : while (val != 0);
526 : 129554648 : return len;
527 : : }
528 : :
529 : : /* Hold the information we need to mmap the file back in. */
530 : :
531 : : struct mmap_info
532 : : {
533 : : size_t offset;
534 : : size_t size;
535 : : void *preferred_base;
536 : : };
537 : :
538 : : /* Write out the state of the compiler to F. */
539 : :
540 : : void
541 : 470 : gt_pch_save (FILE *f)
542 : : {
543 : 470 : const struct ggc_root_tab *const *rt;
544 : 470 : const struct ggc_root_tab *rti;
545 : 470 : size_t i;
546 : 470 : struct traversal_state state;
547 : 470 : char *this_object = NULL;
548 : 470 : size_t this_object_size = 0;
549 : 470 : struct mmap_info mmi;
550 : 470 : const size_t mmap_offset_alignment = host_hooks.gt_pch_alloc_granularity ();
551 : :
552 : 470 : gt_pch_save_stringpool ();
553 : :
554 : 470 : timevar_push (TV_PCH_PTR_REALLOC);
555 : 470 : saving_htab = new hash_table<saving_hasher> (50000);
556 : :
557 : 29516 : for (rt = gt_ggc_rtab; *rt; rt++)
558 : 206424 : for (rti = *rt; rti->base != NULL; rti++)
559 : 4751230 : for (i = 0; i < rti->nelt; i++)
560 : 4573852 : (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
561 : :
562 : : /* Prepare the objects for writing, determine addresses and such. */
563 : 470 : state.f = f;
564 : 470 : state.d = init_ggc_pch ();
565 : 470 : state.count = 0;
566 : 24346849 : saving_htab->traverse <traversal_state *, ggc_call_count> (&state);
567 : :
568 : 470 : mmi.size = ggc_pch_total_size (state.d);
569 : :
570 : : /* Try to arrange things so that no relocation is necessary, but
571 : : don't try very hard. On most platforms, this will always work,
572 : : and on the rest it's a lot of work to do better.
573 : : (The extra work goes in HOST_HOOKS_GT_PCH_GET_ADDRESS and
574 : : HOST_HOOKS_GT_PCH_USE_ADDRESS.) */
575 : 470 : mmi.preferred_base = host_hooks.gt_pch_get_address (mmi.size, fileno (f));
576 : : /* If the host cannot supply any suitable address for this, we are stuck. */
577 : 470 : if (mmi.preferred_base == NULL)
578 : 0 : fatal_error (input_location,
579 : : "cannot write PCH file: required memory segment unavailable");
580 : :
581 : 470 : ggc_pch_this_base (state.d, mmi.preferred_base);
582 : :
583 : 470 : state.ptrs = XNEWVEC (struct ptr_data *, state.count);
584 : 470 : state.ptrs_i = 0;
585 : :
586 : 24346849 : saving_htab->traverse <traversal_state *, ggc_call_alloc> (&state);
587 : 470 : timevar_pop (TV_PCH_PTR_REALLOC);
588 : :
589 : 470 : timevar_push (TV_PCH_PTR_SORT);
590 : 470 : qsort (state.ptrs, state.count, sizeof (*state.ptrs), compare_ptr_data);
591 : 470 : timevar_pop (TV_PCH_PTR_SORT);
592 : :
593 : : /* Write out all the scalar variables. */
594 : 9024 : for (rt = gt_pch_scalar_rtab; *rt; rt++)
595 : 27166 : for (rti = *rt; rti->base != NULL; rti++)
596 : 19082 : if (fwrite (rti->base, rti->stride, 1, f) != 1)
597 : 0 : fatal_error (input_location, "cannot write PCH file: %m");
598 : :
599 : : /* Write out all the global pointers, after translation. */
600 : 470 : write_pch_globals (gt_ggc_rtab, &state);
601 : :
602 : : /* Pad the PCH file so that the mmapped area starts on an allocation
603 : : granularity (usually page) boundary. */
604 : 470 : {
605 : 470 : long o;
606 : 470 : o = ftell (state.f) + sizeof (mmi);
607 : 470 : if (o == -1)
608 : 0 : fatal_error (input_location, "cannot get position in PCH file: %m");
609 : 470 : mmi.offset = mmap_offset_alignment - o % mmap_offset_alignment;
610 : 470 : if (mmi.offset == mmap_offset_alignment)
611 : 0 : mmi.offset = 0;
612 : 470 : mmi.offset += o;
613 : : }
614 : 470 : if (fwrite (&mmi, sizeof (mmi), 1, state.f) != 1)
615 : 0 : fatal_error (input_location, "cannot write PCH file: %m");
616 : 470 : if (mmi.offset != 0
617 : 470 : && fseek (state.f, mmi.offset, SEEK_SET) != 0)
618 : 0 : fatal_error (input_location, "cannot write padding to PCH file: %m");
619 : :
620 : 470 : ggc_pch_prepare_write (state.d, state.f);
621 : :
622 : : #if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
623 : : vec<char> vbits = vNULL;
624 : : #endif
625 : :
626 : : /* Actually write out the objects. */
627 : 24346849 : for (i = 0; i < state.count; i++)
628 : : {
629 : 24346379 : state.ptrs_i = i;
630 : 24346379 : if (this_object_size < state.ptrs[i]->size)
631 : : {
632 : 7240 : this_object_size = state.ptrs[i]->size;
633 : 7240 : this_object = XRESIZEVAR (char, this_object, this_object_size);
634 : : }
635 : : #if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
636 : : /* obj might contain uninitialized bytes, e.g. in the trailing
637 : : padding of the object. Avoid warnings by making the memory
638 : : temporarily defined and then restoring previous state. */
639 : : int get_vbits = 0;
640 : : size_t valid_size = state.ptrs[i]->size;
641 : : if (UNLIKELY (RUNNING_ON_VALGRIND))
642 : : {
643 : : if (vbits.length () < valid_size)
644 : : vbits.safe_grow (valid_size, true);
645 : : get_vbits = VALGRIND_GET_VBITS (state.ptrs[i]->obj,
646 : : vbits.address (), valid_size);
647 : : if (get_vbits == 3)
648 : : {
649 : : /* We assume that first part of obj is addressable, and
650 : : the rest is unaddressable. Find out where the boundary is
651 : : using binary search. */
652 : : size_t lo = 0, hi = valid_size;
653 : : while (hi > lo)
654 : : {
655 : : size_t mid = (lo + hi) / 2;
656 : : get_vbits = VALGRIND_GET_VBITS ((char *) state.ptrs[i]->obj
657 : : + mid, vbits.address (),
658 : : 1);
659 : : if (get_vbits == 3)
660 : : hi = mid;
661 : : else if (get_vbits == 1)
662 : : lo = mid + 1;
663 : : else
664 : : break;
665 : : }
666 : : if (get_vbits == 1 || get_vbits == 3)
667 : : {
668 : : valid_size = lo;
669 : : get_vbits = VALGRIND_GET_VBITS (state.ptrs[i]->obj,
670 : : vbits.address (),
671 : : valid_size);
672 : : }
673 : : }
674 : : if (get_vbits == 1)
675 : : VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (state.ptrs[i]->obj,
676 : : state.ptrs[i]->size));
677 : : }
678 : : #endif
679 : 24346379 : memcpy (this_object, state.ptrs[i]->obj, state.ptrs[i]->size);
680 : 24346379 : if (state.ptrs[i]->reorder_fn != NULL)
681 : 15267 : state.ptrs[i]->reorder_fn (state.ptrs[i]->obj,
682 : : state.ptrs[i]->note_ptr_cookie,
683 : : relocate_ptrs, &state);
684 : 24346379 : gt_note_pointers note_ptr_fn = state.ptrs[i]->note_ptr_fn;
685 : 24346379 : gcc_checking_assert (note_ptr_fn != NULL);
686 : : /* 'gt_pch_p_S' enables certain special handling, but otherwise
687 : : corresponds to no 'note_ptr_fn'. */
688 : 24346379 : if (note_ptr_fn == gt_pch_p_S)
689 : : note_ptr_fn = NULL;
690 : 22137692 : if (note_ptr_fn != NULL)
691 : 22137692 : note_ptr_fn (state.ptrs[i]->obj, state.ptrs[i]->note_ptr_cookie,
692 : : relocate_ptrs, &state);
693 : 24346379 : ggc_pch_write_object (state.d, state.f, state.ptrs[i]->obj,
694 : 24346379 : state.ptrs[i]->new_addr, state.ptrs[i]->size);
695 : 24346379 : if (state.ptrs[i]->reorder_fn != NULL
696 : 24331112 : || note_ptr_fn != NULL)
697 : 22137692 : memcpy (state.ptrs[i]->obj, this_object, state.ptrs[i]->size);
698 : : #if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
699 : : if (UNLIKELY (get_vbits == 1))
700 : : {
701 : : (void) VALGRIND_SET_VBITS (state.ptrs[i]->obj, vbits.address (),
702 : : valid_size);
703 : : if (valid_size != state.ptrs[i]->size)
704 : : VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *)
705 : : state.ptrs[i]->obj
706 : : + valid_size,
707 : : state.ptrs[i]->size
708 : : - valid_size));
709 : : }
710 : : #endif
711 : : }
712 : : #if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
713 : : vbits.release ();
714 : : #endif
715 : :
716 : 470 : reloc_addrs_vec.qsort (compare_ptr);
717 : :
718 : 470 : size_t reloc_addrs_size = 0;
719 : 470 : void *last_addr = NULL;
720 : 470 : unsigned char uleb128_buf[sizeof (size_t) * 2];
721 : 64778734 : for (void *addr : reloc_addrs_vec)
722 : : {
723 : 64777324 : gcc_assert ((uintptr_t) addr >= (uintptr_t) mmi.preferred_base
724 : : && ((uintptr_t) addr + sizeof (void *)
725 : : <= (uintptr_t) mmi.preferred_base + mmi.size));
726 : 64777324 : if (addr == last_addr)
727 : 0 : continue;
728 : 64777324 : if (last_addr == NULL)
729 : 470 : last_addr = mmi.preferred_base;
730 : 64777324 : size_t diff = (uintptr_t) addr - (uintptr_t) last_addr;
731 : 64777324 : reloc_addrs_size += write_uleb128 (uleb128_buf, diff);
732 : 64777324 : last_addr = addr;
733 : : }
734 : 470 : if (fwrite (&reloc_addrs_size, sizeof (reloc_addrs_size), 1, f) != 1)
735 : 0 : fatal_error (input_location, "cannot write PCH file: %m");
736 : 470 : last_addr = NULL;
737 : 64778734 : for (void *addr : reloc_addrs_vec)
738 : : {
739 : 64777324 : if (addr == last_addr)
740 : 0 : continue;
741 : 64777324 : if (last_addr == NULL)
742 : 470 : last_addr = mmi.preferred_base;
743 : 64777324 : size_t diff = (uintptr_t) addr - (uintptr_t) last_addr;
744 : 64777324 : reloc_addrs_size = write_uleb128 (uleb128_buf, diff);
745 : 64777324 : if (fwrite (uleb128_buf, 1, reloc_addrs_size, f) != reloc_addrs_size)
746 : 0 : fatal_error (input_location, "cannot write PCH file: %m");
747 : : last_addr = addr;
748 : : }
749 : :
750 : 470 : ggc_pch_finish (state.d, state.f);
751 : :
752 : 470 : gt_pch_fixup_stringpool ();
753 : :
754 : 470 : unsigned num_callbacks = callback_vec.length ();
755 : 470 : void (*pch_save) (FILE *) = >_pch_save;
756 : 470 : if (fwrite (&pch_save, sizeof (pch_save), 1, f) != 1
757 : 470 : || fwrite (&num_callbacks, sizeof (num_callbacks), 1, f) != 1
758 : 940 : || (num_callbacks
759 : 940 : && fwrite (callback_vec.address (), sizeof (void *), num_callbacks,
760 : 470 : f) != num_callbacks))
761 : 0 : fatal_error (input_location, "cannot write PCH file: %m");
762 : :
763 : 470 : XDELETE (state.ptrs);
764 : 470 : XDELETE (this_object);
765 : 470 : delete saving_htab;
766 : 470 : saving_htab = NULL;
767 : 470 : callback_vec.release ();
768 : 470 : reloc_addrs_vec.release ();
769 : 470 : }
770 : :
771 : : /* Read the state of the compiler back in from F. */
772 : :
773 : : void
774 : 347 : gt_pch_restore (FILE *f)
775 : : {
776 : 347 : const struct ggc_root_tab *const *rt;
777 : 347 : const struct ggc_root_tab *rti;
778 : 347 : size_t i;
779 : 347 : struct mmap_info mmi;
780 : 347 : int result;
781 : :
782 : : /* We are about to reload the line maps along with the rest of the PCH
783 : : data, which means that the (loaded) ones cannot be guaranteed to be
784 : : in any valid state for reporting diagnostics that happen during the
785 : : load. Save the current table (and use it during the loading process
786 : : below). */
787 : 347 : class line_maps *save_line_table = line_table;
788 : :
789 : : /* Delete any deletable objects. This makes ggc_pch_read much
790 : : faster, as it can be sure that no GCable objects remain other
791 : : than the ones just read in. */
792 : 4647 : for (rt = gt_ggc_deletable_rtab; *rt; rt++)
793 : 10554 : for (rti = *rt; rti->base != NULL; rti++)
794 : 6254 : memset (rti->base, 0, rti->stride);
795 : :
796 : : /* Read in all the scalar variables. */
797 : 6397 : for (rt = gt_pch_scalar_rtab; *rt; rt++)
798 : 20247 : for (rti = *rt; rti->base != NULL; rti++)
799 : 14197 : if (fread (rti->base, rti->stride, 1, f) != 1)
800 : 0 : fatal_error (input_location, "cannot read PCH file: %m");
801 : :
802 : : /* Read in all the global pointers, in 6 easy loops. */
803 : : bool error_reading_pointers = false;
804 : 22118 : for (rt = gt_ggc_rtab; *rt; rt++)
805 : 154048 : for (rti = *rt; rti->base != NULL; rti++)
806 : 3516391 : for (i = 0; i < rti->nelt; i++)
807 : 3384114 : if (fread ((char *)rti->base + rti->stride * i,
808 : : sizeof (void *), 1, f) != 1)
809 : 0 : error_reading_pointers = true;
810 : :
811 : : /* Stash the newly read-in line table pointer - it does not point to
812 : : anything meaningful yet, so swap the old one back in. */
813 : 347 : class line_maps *new_line_table = line_table;
814 : 347 : line_table = save_line_table;
815 : 347 : if (error_reading_pointers)
816 : 0 : fatal_error (input_location, "cannot read PCH file: %m");
817 : :
818 : 347 : if (fread (&mmi, sizeof (mmi), 1, f) != 1)
819 : 0 : fatal_error (input_location, "cannot read PCH file: %m");
820 : :
821 : 347 : void *orig_preferred_base = mmi.preferred_base;
822 : 347 : result = host_hooks.gt_pch_use_address (mmi.preferred_base, mmi.size,
823 : : fileno (f), mmi.offset);
824 : :
825 : : /* We could not mmap or otherwise allocate the required memory at the
826 : : address needed. */
827 : 347 : if (result < 0)
828 : : {
829 : 0 : sorry_at (input_location, "PCH allocation failure");
830 : : /* There is no point in continuing from here, we will only end up
831 : : with a crashed (most likely hanging) compiler. */
832 : 0 : exit (-1);
833 : : }
834 : :
835 : : /* (0) We allocated memory, but did not mmap the file, so we need to read
836 : : the data in manually. (>0) Otherwise the mmap succeed for the address
837 : : we wanted. */
838 : 347 : if (result == 0)
839 : : {
840 : 0 : if (fseek (f, mmi.offset, SEEK_SET) != 0
841 : 0 : || fread (mmi.preferred_base, mmi.size, 1, f) != 1)
842 : 0 : fatal_error (input_location, "cannot read PCH file: %m");
843 : : }
844 : 347 : else if (fseek (f, mmi.offset + mmi.size, SEEK_SET) != 0)
845 : 0 : fatal_error (input_location, "cannot read PCH file: %m");
846 : :
847 : 347 : size_t reloc_addrs_size;
848 : 347 : if (fread (&reloc_addrs_size, sizeof (reloc_addrs_size), 1, f) != 1)
849 : 0 : fatal_error (input_location, "cannot read PCH file: %m");
850 : :
851 : 347 : if (orig_preferred_base != mmi.preferred_base)
852 : : {
853 : 0 : uintptr_t bias
854 : 0 : = (uintptr_t) mmi.preferred_base - (uintptr_t) orig_preferred_base;
855 : :
856 : : /* Adjust all the global pointers by bias. */
857 : 0 : line_table = new_line_table;
858 : 0 : for (rt = gt_ggc_rtab; *rt; rt++)
859 : 0 : for (rti = *rt; rti->base != NULL; rti++)
860 : 0 : for (i = 0; i < rti->nelt; i++)
861 : : {
862 : 0 : char *addr = (char *)rti->base + rti->stride * i;
863 : 0 : char *p;
864 : 0 : memcpy (&p, addr, sizeof (void *));
865 : 0 : if ((uintptr_t) p >= (uintptr_t) orig_preferred_base
866 : 0 : && (uintptr_t) p < (uintptr_t) orig_preferred_base + mmi.size)
867 : : {
868 : 0 : p = (char *) ((uintptr_t) p + bias);
869 : 0 : memcpy (addr, &p, sizeof (void *));
870 : : }
871 : : }
872 : 0 : new_line_table = line_table;
873 : 0 : line_table = save_line_table;
874 : :
875 : : /* And adjust all the pointers in the image by bias too. */
876 : 0 : char *addr = (char *) mmi.preferred_base;
877 : 0 : unsigned char uleb128_buf[4096], *uleb128_ptr = uleb128_buf;
878 : 0 : while (reloc_addrs_size != 0)
879 : : {
880 : 0 : size_t this_size
881 : 0 : = MIN (reloc_addrs_size,
882 : : (size_t) (4096 - (uleb128_ptr - uleb128_buf)));
883 : 0 : if (fread (uleb128_ptr, 1, this_size, f) != this_size)
884 : 0 : fatal_error (input_location, "cannot read PCH file: %m");
885 : 0 : unsigned char *uleb128_end = uleb128_ptr + this_size;
886 : 0 : if (this_size != reloc_addrs_size)
887 : 0 : uleb128_end -= 2 * sizeof (size_t);
888 : 0 : uleb128_ptr = uleb128_buf;
889 : 0 : while (uleb128_ptr < uleb128_end)
890 : : {
891 : : size_t diff;
892 : 0 : uleb128_ptr = read_uleb128 (uleb128_ptr, &diff);
893 : 0 : addr = (char *) ((uintptr_t) addr + diff);
894 : :
895 : 0 : char *p;
896 : 0 : memcpy (&p, addr, sizeof (void *));
897 : 0 : gcc_assert ((uintptr_t) p >= (uintptr_t) orig_preferred_base
898 : : && ((uintptr_t) p
899 : : < (uintptr_t) orig_preferred_base + mmi.size));
900 : 0 : p = (char *) ((uintptr_t) p + bias);
901 : 0 : memcpy (addr, &p, sizeof (void *));
902 : : }
903 : 0 : reloc_addrs_size -= this_size;
904 : 0 : if (reloc_addrs_size == 0)
905 : : break;
906 : 0 : this_size = uleb128_end + 2 * sizeof (size_t) - uleb128_ptr;
907 : 0 : memcpy (uleb128_buf, uleb128_ptr, this_size);
908 : 0 : uleb128_ptr = uleb128_buf + this_size;
909 : : }
910 : : }
911 : 347 : else if (fseek (f, (mmi.offset + mmi.size + sizeof (reloc_addrs_size)
912 : 347 : + reloc_addrs_size), SEEK_SET) != 0)
913 : 0 : fatal_error (input_location, "cannot read PCH file: %m");
914 : :
915 : 347 : ggc_pch_read (f, mmi.preferred_base);
916 : :
917 : 347 : void (*pch_save) (FILE *);
918 : 347 : unsigned num_callbacks;
919 : 347 : if (fread (&pch_save, sizeof (pch_save), 1, f) != 1
920 : 347 : || fread (&num_callbacks, sizeof (num_callbacks), 1, f) != 1)
921 : 0 : fatal_error (input_location, "cannot read PCH file: %m");
922 : 347 : if (pch_save != >_pch_save)
923 : : {
924 : 0 : uintptr_t binbias = (uintptr_t) >_pch_save - (uintptr_t) pch_save;
925 : 0 : void **ptrs = XNEWVEC (void *, num_callbacks);
926 : 0 : unsigned i;
927 : 0 : uintptr_t bias
928 : 0 : = (uintptr_t) mmi.preferred_base - (uintptr_t) orig_preferred_base;
929 : :
930 : 0 : if (fread (ptrs, sizeof (void *), num_callbacks, f) != num_callbacks)
931 : 0 : fatal_error (input_location, "cannot read PCH file: %m");
932 : 0 : for (i = 0; i < num_callbacks; ++i)
933 : : {
934 : 0 : void *ptr = (void *) ((uintptr_t) ptrs[i] + bias);
935 : 0 : memcpy (&pch_save, ptr, sizeof (pch_save));
936 : 0 : pch_save = (void (*) (FILE *)) ((uintptr_t) pch_save + binbias);
937 : 0 : memcpy (ptr, &pch_save, sizeof (pch_save));
938 : : }
939 : 0 : XDELETE (ptrs);
940 : : }
941 : 347 : else if (fseek (f, num_callbacks * sizeof (void *), SEEK_CUR) != 0)
942 : 0 : fatal_error (input_location, "cannot read PCH file: %m");
943 : :
944 : 347 : gt_pch_restore_stringpool ();
945 : :
946 : : /* Barring corruption of the PCH file, the restored line table should be
947 : : complete and usable. */
948 : 347 : line_table = new_line_table;
949 : 347 : }
950 : :
951 : : /* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is not present.
952 : : Select no address whatsoever, and let gt_pch_save choose what it will with
953 : : malloc, presumably. */
954 : :
955 : : void *
956 : 0 : default_gt_pch_get_address (size_t size ATTRIBUTE_UNUSED,
957 : : int fd ATTRIBUTE_UNUSED)
958 : : {
959 : 0 : return NULL;
960 : : }
961 : :
962 : : /* Default version of HOST_HOOKS_GT_PCH_USE_ADDRESS when mmap is not present.
963 : : Allocate SIZE bytes with malloc. Return 0 if the address we got is the
964 : : same as base, indicating that the memory has been allocated but needs to
965 : : be read in from the file. Return -1 if the address differs, to relocation
966 : : of the PCH file would be required. */
967 : :
968 : : int
969 : 0 : default_gt_pch_use_address (void *&base, size_t size, int fd ATTRIBUTE_UNUSED,
970 : : size_t offset ATTRIBUTE_UNUSED)
971 : : {
972 : 0 : void *addr = xmalloc (size);
973 : 0 : return (addr == base) - 1;
974 : : }
975 : :
976 : : /* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS. Return the
977 : : alignment required for allocating virtual memory. Usually this is the
978 : : same as pagesize. */
979 : :
980 : : size_t
981 : 470 : default_gt_pch_alloc_granularity (void)
982 : : {
983 : 470 : return getpagesize ();
984 : : }
985 : :
986 : : #if HAVE_MMAP_FILE
987 : : /* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is present.
988 : : We temporarily allocate SIZE bytes, and let the kernel place the data
989 : : wherever it will. If it worked, that's our spot, if not we're likely
990 : : to be in trouble. */
991 : :
992 : : void *
993 : 0 : mmap_gt_pch_get_address (size_t size, int fd)
994 : : {
995 : 0 : void *ret;
996 : :
997 : 0 : ret = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
998 : 0 : if (ret == (void *) MAP_FAILED)
999 : : ret = NULL;
1000 : : else
1001 : 0 : munmap ((caddr_t) ret, size);
1002 : :
1003 : 0 : return ret;
1004 : : }
1005 : :
1006 : : /* Default version of HOST_HOOKS_GT_PCH_USE_ADDRESS when mmap is present.
1007 : : Map SIZE bytes of FD+OFFSET at BASE. Return 1 if we succeeded at
1008 : : mapping the data at BASE, -1 if we couldn't.
1009 : :
1010 : : This version assumes that the kernel honors the START operand of mmap
1011 : : even without MAP_FIXED if START through START+SIZE are not currently
1012 : : mapped with something. */
1013 : :
1014 : : int
1015 : 0 : mmap_gt_pch_use_address (void *&base, size_t size, int fd, size_t offset)
1016 : : {
1017 : 0 : void *addr;
1018 : :
1019 : : /* We're called with size == 0 if we're not planning to load a PCH
1020 : : file at all. This allows the hook to free any static space that
1021 : : we might have allocated at link time. */
1022 : 0 : if (size == 0)
1023 : : return -1;
1024 : :
1025 : 0 : addr = mmap ((caddr_t) base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
1026 : : fd, offset);
1027 : :
1028 : 0 : return addr == base ? 1 : -1;
1029 : : }
1030 : : #endif /* HAVE_MMAP_FILE */
1031 : :
1032 : : #if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
1033 : :
1034 : : /* Modify the bound based on rlimits. */
1035 : : static double
1036 : : ggc_rlimit_bound (double limit)
1037 : : {
1038 : : #if defined(HAVE_GETRLIMIT)
1039 : : struct rlimit rlim;
1040 : : # if defined (RLIMIT_AS)
1041 : : /* RLIMIT_AS is what POSIX says is the limit on mmap. Presumably
1042 : : any OS which has RLIMIT_AS also has a working mmap that GCC will use. */
1043 : : if (getrlimit (RLIMIT_AS, &rlim) == 0
1044 : : && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
1045 : : && rlim.rlim_cur < limit)
1046 : : limit = rlim.rlim_cur;
1047 : : # elif defined (RLIMIT_DATA)
1048 : : /* ... but some older OSs bound mmap based on RLIMIT_DATA, or we
1049 : : might be on an OS that has a broken mmap. (Others don't bound
1050 : : mmap at all, apparently.) */
1051 : : if (getrlimit (RLIMIT_DATA, &rlim) == 0
1052 : : && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
1053 : : && rlim.rlim_cur < limit
1054 : : /* Darwin has this horribly bogus default setting of
1055 : : RLIMIT_DATA, to 6144Kb. No-one notices because RLIMIT_DATA
1056 : : appears to be ignored. Ignore such silliness. If a limit
1057 : : this small was actually effective for mmap, GCC wouldn't even
1058 : : start up. */
1059 : : && rlim.rlim_cur >= 8 * ONE_M)
1060 : : limit = rlim.rlim_cur;
1061 : : # endif /* RLIMIT_AS or RLIMIT_DATA */
1062 : : #endif /* HAVE_GETRLIMIT */
1063 : :
1064 : : return limit;
1065 : : }
1066 : :
1067 : : /* Heuristic to set a default for GGC_MIN_EXPAND. */
1068 : : static int
1069 : : ggc_min_expand_heuristic (void)
1070 : : {
1071 : : double min_expand = physmem_total ();
1072 : :
1073 : : /* Adjust for rlimits. */
1074 : : min_expand = ggc_rlimit_bound (min_expand);
1075 : :
1076 : : /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding
1077 : : a lower bound of 30% and an upper bound of 100% (when RAM >= 1GB). */
1078 : : min_expand /= ONE_G;
1079 : : min_expand *= 70;
1080 : : min_expand = MIN (min_expand, 70);
1081 : : min_expand += 30;
1082 : :
1083 : : return min_expand;
1084 : : }
1085 : :
1086 : : /* Heuristic to set a default for GGC_MIN_HEAPSIZE. */
1087 : : static int
1088 : : ggc_min_heapsize_heuristic (void)
1089 : : {
1090 : : double phys_kbytes = physmem_total ();
1091 : : double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2);
1092 : :
1093 : : phys_kbytes /= ONE_K; /* Convert to Kbytes. */
1094 : : limit_kbytes /= ONE_K;
1095 : :
1096 : : /* The heuristic is RAM/8, with a lower bound of 4M and an upper
1097 : : bound of 128M (when RAM >= 1GB). */
1098 : : phys_kbytes /= 8;
1099 : :
1100 : : #if defined(HAVE_GETRLIMIT) && defined (RLIMIT_RSS)
1101 : : /* Try not to overrun the RSS limit while doing garbage collection.
1102 : : The RSS limit is only advisory, so no margin is subtracted. */
1103 : : {
1104 : : struct rlimit rlim;
1105 : : if (getrlimit (RLIMIT_RSS, &rlim) == 0
1106 : : && rlim.rlim_cur != (rlim_t) RLIM_INFINITY)
1107 : : phys_kbytes = MIN (phys_kbytes, rlim.rlim_cur / ONE_K);
1108 : : }
1109 : : # endif
1110 : :
1111 : : /* Don't blindly run over our data limit; do GC at least when the
1112 : : *next* GC would be within 20Mb of the limit or within a quarter of
1113 : : the limit, whichever is larger. If GCC does hit the data limit,
1114 : : compilation will fail, so this tries to be conservative. */
1115 : : limit_kbytes = MAX (0, limit_kbytes - MAX (limit_kbytes / 4, 20 * ONE_K));
1116 : : limit_kbytes = (limit_kbytes * 100) / (110 + ggc_min_expand_heuristic ());
1117 : : phys_kbytes = MIN (phys_kbytes, limit_kbytes);
1118 : :
1119 : : phys_kbytes = MAX (phys_kbytes, 4 * ONE_K);
1120 : : phys_kbytes = MIN (phys_kbytes, 128 * ONE_K);
1121 : :
1122 : : return phys_kbytes;
1123 : : }
1124 : : #endif
1125 : :
1126 : : void
1127 : 282866 : init_ggc_heuristics (void)
1128 : : {
1129 : : #if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
1130 : : param_ggc_min_expand = ggc_min_expand_heuristic ();
1131 : : param_ggc_min_heapsize = ggc_min_heapsize_heuristic ();
1132 : : #endif
1133 : 282866 : }
1134 : :
1135 : : /* GGC memory usage. */
1136 : : class ggc_usage: public mem_usage
1137 : : {
1138 : : public:
1139 : : /* Default constructor. */
1140 : 0 : ggc_usage (): m_freed (0), m_collected (0), m_overhead (0) {}
1141 : : /* Constructor. */
1142 : : ggc_usage (size_t allocated, size_t times, size_t peak,
1143 : : size_t freed, size_t collected, size_t overhead)
1144 : : : mem_usage (allocated, times, peak),
1145 : : m_freed (freed), m_collected (collected), m_overhead (overhead) {}
1146 : :
1147 : : /* Equality operator. */
1148 : : inline bool
1149 : : operator== (const ggc_usage &second) const
1150 : : {
1151 : : return (get_balance () == second.get_balance ()
1152 : : && m_peak == second.m_peak
1153 : : && m_times == second.m_times);
1154 : : }
1155 : :
1156 : : /* Comparison operator. */
1157 : : inline bool
1158 : : operator< (const ggc_usage &second) const
1159 : : {
1160 : : if (*this == second)
1161 : : return false;
1162 : :
1163 : : return (get_balance () == second.get_balance () ?
1164 : : (m_peak == second.m_peak ? m_times < second.m_times
1165 : : : m_peak < second.m_peak)
1166 : : : get_balance () < second.get_balance ());
1167 : : }
1168 : :
1169 : : /* Register overhead of ALLOCATED and OVERHEAD bytes. */
1170 : : inline void
1171 : 0 : register_overhead (size_t allocated, size_t overhead)
1172 : : {
1173 : 0 : m_allocated += allocated;
1174 : 0 : m_overhead += overhead;
1175 : 0 : m_times++;
1176 : : }
1177 : :
1178 : : /* Release overhead of SIZE bytes. */
1179 : : inline void
1180 : 0 : release_overhead (size_t size)
1181 : : {
1182 : 0 : m_freed += size;
1183 : : }
1184 : :
1185 : : /* Sum the usage with SECOND usage. */
1186 : : ggc_usage
1187 : : operator+ (const ggc_usage &second)
1188 : : {
1189 : : return ggc_usage (m_allocated + second.m_allocated,
1190 : : m_times + second.m_times,
1191 : : m_peak + second.m_peak,
1192 : : m_freed + second.m_freed,
1193 : : m_collected + second.m_collected,
1194 : : m_overhead + second.m_overhead);
1195 : : }
1196 : :
1197 : : /* Dump usage with PREFIX, where TOTAL is sum of all rows. */
1198 : : inline void
1199 : : dump (const char *prefix, ggc_usage &total) const
1200 : : {
1201 : : size_t balance = get_balance ();
1202 : : fprintf (stderr,
1203 : : "%-48s " PRsa (9) ":%5.1f%%" PRsa (9) ":%5.1f%%"
1204 : : PRsa (9) ":%5.1f%%" PRsa (9) ":%5.1f%%" PRsa (9) "\n",
1205 : : prefix,
1206 : : SIZE_AMOUNT (balance), get_percent (balance, total.get_balance ()),
1207 : : SIZE_AMOUNT (m_collected),
1208 : : get_percent (m_collected, total.m_collected),
1209 : : SIZE_AMOUNT (m_freed), get_percent (m_freed, total.m_freed),
1210 : : SIZE_AMOUNT (m_overhead),
1211 : : get_percent (m_overhead, total.m_overhead),
1212 : : SIZE_AMOUNT (m_times));
1213 : : }
1214 : :
1215 : : /* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */
1216 : : inline void
1217 : : dump (mem_location *loc, ggc_usage &total) const
1218 : : {
1219 : : char *location_string = loc->to_string ();
1220 : :
1221 : : dump (location_string, total);
1222 : :
1223 : : free (location_string);
1224 : : }
1225 : :
1226 : : /* Dump footer. */
1227 : : inline void
1228 : : dump_footer ()
1229 : : {
1230 : : dump ("Total", *this);
1231 : : }
1232 : :
1233 : : /* Get balance which is GGC allocation leak. */
1234 : : inline size_t
1235 : : get_balance () const
1236 : : {
1237 : : return m_allocated + m_overhead - m_collected - m_freed;
1238 : : }
1239 : :
1240 : : typedef std::pair<mem_location *, ggc_usage *> mem_pair_t;
1241 : :
1242 : : /* Compare wrapper used by qsort method. */
1243 : : static int
1244 : : compare (const void *first, const void *second)
1245 : : {
1246 : : const mem_pair_t mem1 = *(const mem_pair_t *) first;
1247 : : const mem_pair_t mem2 = *(const mem_pair_t *) second;
1248 : :
1249 : : size_t balance1 = mem1.second->get_balance ();
1250 : : size_t balance2 = mem2.second->get_balance ();
1251 : :
1252 : : return balance1 == balance2 ? 0 : (balance1 < balance2 ? 1 : -1);
1253 : : }
1254 : :
1255 : : /* Dump header with NAME. */
1256 : : static inline void
1257 : : dump_header (const char *name)
1258 : : {
1259 : : fprintf (stderr, "%-48s %11s%17s%17s%16s%17s\n", name, "Leak", "Garbage",
1260 : : "Freed", "Overhead", "Times");
1261 : : }
1262 : :
1263 : : /* Freed memory in bytes. */
1264 : : size_t m_freed;
1265 : : /* Collected memory in bytes. */
1266 : : size_t m_collected;
1267 : : /* Overhead memory in bytes. */
1268 : : size_t m_overhead;
1269 : : };
1270 : :
1271 : : /* GCC memory description. */
1272 : : static mem_alloc_description<ggc_usage> ggc_mem_desc;
1273 : :
1274 : : /* Dump per-site memory statistics. */
1275 : :
1276 : : void
1277 : 0 : dump_ggc_loc_statistics ()
1278 : : {
1279 : 0 : if (! GATHER_STATISTICS)
1280 : 0 : return;
1281 : :
1282 : : ggc_collect (GGC_COLLECT_FORCE);
1283 : :
1284 : : ggc_mem_desc.dump (GGC_ORIGIN);
1285 : : }
1286 : :
1287 : : /* Record ALLOCATED and OVERHEAD bytes to descriptor NAME:LINE (FUNCTION). */
1288 : : void
1289 : 0 : ggc_record_overhead (size_t allocated, size_t overhead, void *ptr MEM_STAT_DECL)
1290 : : {
1291 : 0 : ggc_usage *usage = ggc_mem_desc.register_descriptor (ptr, GGC_ORIGIN, false
1292 : : FINAL_PASS_MEM_STAT);
1293 : :
1294 : 0 : ggc_mem_desc.register_object_overhead (usage, allocated + overhead, ptr);
1295 : 0 : usage->register_overhead (allocated, overhead);
1296 : 0 : }
1297 : :
1298 : : /* Notice that the pointer has been freed. */
1299 : : void
1300 : 0 : ggc_free_overhead (void *ptr)
1301 : : {
1302 : 0 : ggc_mem_desc.release_object_overhead (ptr);
1303 : 0 : }
1304 : :
1305 : : /* After live values has been marked, walk all recorded pointers and see if
1306 : : they are still live. */
1307 : : void
1308 : 0 : ggc_prune_overhead_list (void)
1309 : : {
1310 : 0 : typedef hash_map<const void *, std::pair<ggc_usage *, size_t > > map_t;
1311 : :
1312 : 0 : map_t::iterator it = ggc_mem_desc.m_reverse_object_map->begin ();
1313 : :
1314 : 0 : for (; it != ggc_mem_desc.m_reverse_object_map->end (); ++it)
1315 : 0 : if (!ggc_marked_p ((*it).first))
1316 : : {
1317 : 0 : (*it).second.first->m_collected += (*it).second.second;
1318 : 0 : ggc_mem_desc.m_reverse_object_map->remove ((*it).first);
1319 : : }
1320 : 0 : }
1321 : :
1322 : : /* Print memory used by heap if this info is available. */
1323 : :
1324 : : void
1325 : 4686153 : report_heap_memory_use ()
1326 : : {
1327 : : #if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2)
1328 : : #ifdef HAVE_MALLINFO2
1329 : : #define MALLINFO_FN mallinfo2
1330 : : #else
1331 : : #define MALLINFO_FN mallinfo
1332 : : #endif
1333 : 4686153 : if (!quiet_flag)
1334 : 0 : fprintf (stderr, " {heap " PRsa (0) "}",
1335 : 0 : SIZE_AMOUNT (MALLINFO_FN ().arena));
1336 : : #endif
1337 : 4686153 : }
1338 : :
1339 : : /* Forcibly clear all GTY roots. */
1340 : :
1341 : : void
1342 : 255021 : ggc_common_finalize ()
1343 : : {
1344 : 255021 : const struct ggc_root_tab *const *rt;
1345 : 255021 : const_ggc_root_tab_t rti;
1346 : :
1347 : 3415013 : for (rt = gt_ggc_deletable_rtab; *rt; rt++)
1348 : 7840478 : for (rti = *rt; rti->base != NULL; rti++)
1349 : 4680486 : memset (rti->base, 0, rti->stride * rti->nelt);
1350 : :
1351 : 16567859 : for (rt = gt_ggc_rtab; *rt; rt++)
1352 : 16312838 : ggc_zero_rtab_roots (*rt);
1353 : :
1354 : 4653286 : for (rt = gt_pch_scalar_rtab; *rt; rt++)
1355 : 14693005 : for (rti = *rt; rti->base != NULL; rti++)
1356 : 10294740 : memset (rti->base, 0, rti->stride * rti->nelt);
1357 : 255021 : }
|