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