* sv.po: Update.
[official-gcc.git] / gcc / mem-stats.h
blob0b1dda23e71ce71fbffc20259671f329b5ea8ec9
1 /* A memory statistics tracking infrastructure.
2 Copyright (C) 2015-2016 Free Software Foundation, Inc.
3 Contributed by Martin Liska <mliska@suse.cz>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #ifndef GCC_MEM_STATS_H
22 #define GCC_MEM_STATS_H
24 /* Forward declaration. */
25 template<typename Key, typename Value,
26 typename Traits = simple_hashmap_traits<default_hash_traits<Key>,
27 Value> >
28 class hash_map;
30 #define LOCATION_LINE_EXTRA_SPACE 30
31 #define LOCATION_LINE_WIDTH 48
33 /* Memory allocation location. */
34 struct mem_location
36 /* Default constructor. */
37 inline
38 mem_location () {}
40 /* Constructor. */
41 inline
42 mem_location (mem_alloc_origin origin, bool ggc,
43 const char *filename = NULL, int line = 0,
44 const char *function = NULL):
45 m_filename (filename), m_function (function), m_line (line), m_origin
46 (origin), m_ggc (ggc) {}
48 /* Copy constructor. */
49 inline
50 mem_location (mem_location &other): m_filename (other.m_filename),
51 m_function (other.m_function), m_line (other.m_line),
52 m_origin (other.m_origin), m_ggc (other.m_ggc) {}
54 /* Compute hash value based on file name, function name and line in
55 source code. As there is just a single pointer registered for every
56 constant that points to e.g. the same file name, we can use hash
57 of the pointer. */
58 hashval_t
59 hash ()
61 inchash::hash hash;
63 hash.add_ptr (m_filename);
64 hash.add_ptr (m_function);
65 hash.add_int (m_line);
67 return hash.end ();
70 /* Return true if the memory location is equal to OTHER. */
71 int
72 equal (mem_location &other)
74 return m_filename == other.m_filename && m_function == other.m_function
75 && m_line == other.m_line;
78 /* Return trimmed filename for the location. */
79 inline const char *
80 get_trimmed_filename ()
82 const char *s1 = m_filename;
83 const char *s2;
85 while ((s2 = strstr (s1, "gcc/")))
86 s1 = s2 + 4;
88 return s1;
91 inline char *
92 to_string ()
94 unsigned l = strlen (get_trimmed_filename ()) + strlen (m_function)
95 + LOCATION_LINE_EXTRA_SPACE;
97 char *s = XNEWVEC (char, l);
98 sprintf (s, "%s:%i (%s)", get_trimmed_filename (),
99 m_line, m_function);
101 s[MIN (LOCATION_LINE_WIDTH, l - 1)] = '\0';
103 return s;
106 /* Return display name associated to ORIGIN type. */
107 static const char *
108 get_origin_name (mem_alloc_origin origin)
110 return mem_alloc_origin_names[(unsigned) origin];
113 /* File name of source code. */
114 const char *m_filename;
115 /* Funcation name. */
116 const char *m_function;
117 /* Line number in source code. */
118 int m_line;
119 /* Origin type. */
120 mem_alloc_origin m_origin;
121 /* Flag if used by GGC allocation. */
122 bool m_ggc;
125 /* Memory usage register to a memory location. */
126 struct mem_usage
128 /* Default constructor. */
129 mem_usage (): m_allocated (0), m_times (0), m_peak (0), m_instances (1) {}
131 /* Constructor. */
132 mem_usage (size_t allocated, size_t times, size_t peak, size_t instances = 0):
133 m_allocated (allocated), m_times (times), m_peak (peak),
134 m_instances (instances) {}
136 /* Register overhead of SIZE bytes. */
137 inline void
138 register_overhead (size_t size)
140 m_allocated += size;
141 m_times++;
143 if (m_peak < m_allocated)
144 m_peak = m_allocated;
147 /* Release overhead of SIZE bytes. */
148 inline void
149 release_overhead (size_t size)
151 gcc_assert (size <= m_allocated);
153 m_allocated -= size;
156 /* Sum the usage with SECOND usage. */
157 mem_usage
158 operator+ (const mem_usage &second)
160 return mem_usage (m_allocated + second.m_allocated,
161 m_times + second.m_times,
162 m_peak + second.m_peak,
163 m_instances + second.m_instances);
166 /* Comparison operator. */
167 inline bool
168 operator< (const mem_usage &second) const
170 return (m_allocated == second.m_allocated ?
171 (m_peak == second.m_peak ? m_times < second.m_times
172 : m_peak < second.m_peak) : m_allocated < second.m_allocated);
175 /* Compare wrapper used by qsort method. */
176 static int
177 compare (const void *first, const void *second)
179 typedef std::pair<mem_location *, mem_usage *> mem_pair_t;
181 const mem_pair_t f = *(const mem_pair_t *)first;
182 const mem_pair_t s = *(const mem_pair_t *)second;
184 return (*f.second) < (*s.second);
187 /* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */
188 inline void
189 dump (mem_location *loc, mem_usage &total) const
191 char *location_string = loc->to_string ();
193 fprintf (stderr, "%-48s %10li:%5.1f%%%10li%10li:%5.1f%%%10s\n",
194 location_string,
195 (long)m_allocated, get_percent (m_allocated, total.m_allocated),
196 (long)m_peak, (long)m_times,
197 get_percent (m_times, total.m_times), loc->m_ggc ? "ggc" : "heap");
199 free (location_string);
202 /* Dump footer. */
203 inline void
204 dump_footer () const
206 print_dash_line ();
207 fprintf (stderr, "%s%54li%27li\n", "Total", (long)m_allocated,
208 (long)m_times);
209 print_dash_line ();
212 /* Return fraction of NOMINATOR and DENOMINATOR in percent. */
213 static inline float
214 get_percent (size_t nominator, size_t denominator)
216 return denominator == 0 ? 0.0f : nominator * 100.0 / denominator;
219 /* Print line made of dashes. */
220 static inline void
221 print_dash_line (size_t count = 140)
223 while (count--)
224 fputc ('-', stderr);
225 fputc ('\n', stderr);
228 /* Dump header with NAME. */
229 static inline void
230 dump_header (const char *name)
232 fprintf (stderr, "%-48s %11s%16s%10s%17s\n", name, "Leak", "Peak",
233 "Times", "Type");
234 print_dash_line ();
237 /* Current number of allocated bytes. */
238 size_t m_allocated;
239 /* Number of allocations. */
240 size_t m_times;
241 /* Peak allocation in bytes. */
242 size_t m_peak;
243 /* Number of container instances. */
244 size_t m_instances;
247 /* Memory usage pair that connectes memory usage and number
248 of allocated bytes. */
249 template <class T>
250 struct mem_usage_pair
252 mem_usage_pair (T *usage_, size_t allocated_): usage (usage_),
253 allocated (allocated_) {}
255 T *usage;
256 size_t allocated;
259 /* Memory allocation description. */
260 template <class T>
261 class mem_alloc_description
263 public:
264 struct mem_location_hash : nofree_ptr_hash <mem_location>
266 static hashval_t
267 hash (value_type l)
269 inchash::hash hstate;
271 hstate.add_ptr ((const void *)l->m_filename);
272 hstate.add_ptr (l->m_function);
273 hstate.add_int (l->m_line);
275 return hstate.end ();
278 static bool
279 equal (value_type l1, value_type l2)
281 return l1->m_filename == l2->m_filename
282 && l1->m_function == l2->m_function
283 && l1->m_line == l2->m_line;
287 /* Internal class type definitions. */
288 typedef hash_map <mem_location_hash, T *> mem_map_t;
289 typedef hash_map <const void *, mem_usage_pair<T> > reverse_mem_map_t;
290 typedef hash_map <const void *, std::pair<T *, size_t> > reverse_object_map_t;
291 typedef std::pair <mem_location *, T *> mem_list_t;
293 /* Default contructor. */
294 mem_alloc_description ();
296 /* Default destructor. */
297 ~mem_alloc_description ();
299 /* Returns true if instance PTR is registered by the memory description. */
300 bool
301 contains_descriptor_for_instance (const void *ptr);
303 /* Return descriptor for instance PTR. */
305 get_descriptor_for_instance (const void *ptr);
307 /* Register memory allocation descriptor for container PTR which is
308 described by a memory LOCATION. */
310 register_descriptor (const void *ptr, mem_location *location);
312 /* Register memory allocation descriptor for container PTR. ORIGIN identifies
313 type of container and GGC identifes if the allocation is handled in GGC
314 memory. Each location is identified by file NAME, LINE in source code and
315 FUNCTION name. */
317 register_descriptor (const void *ptr, mem_alloc_origin origin,
318 bool ggc, const char *name, int line,
319 const char *function);
321 /* Register instance overhead identified by PTR pointer. Allocation takes
322 SIZE bytes. */
324 register_instance_overhead (size_t size, const void *ptr);
326 /* For containers (and GGC) where we want to track every instance object,
327 we register allocation of SIZE bytes, identified by PTR pointer, belonging
328 to USAGE descriptor. */
329 void
330 register_object_overhead (T *usage, size_t size, const void *ptr);
332 /* Release PTR pointer of SIZE bytes. If REMOVE_FROM_MAP is set to true,
333 remove the instance from reverse map. */
334 void
335 release_instance_overhead (void *ptr, size_t size,
336 bool remove_from_map = false);
338 /* Release intance object identified by PTR pointer. */
339 void
340 release_object_overhead (void *ptr);
342 /* Get sum value for ORIGIN type of allocation for the descriptor. */
344 get_sum (mem_alloc_origin origin);
346 /* Get all tracked instances registered by the description. Items
347 are filtered by ORIGIN type, LENGTH is return value where we register
348 the number of elements in the list. If we want to process custom order,
349 CMP comparator can be provided. */
350 mem_list_t *
351 get_list (mem_alloc_origin origin, unsigned *length,
352 int (*cmp) (const void *first, const void *second) = NULL);
354 /* Dump all tracked instances of type ORIGIN. If we want to process custom
355 order, CMP comparator can be provided. */
356 void dump (mem_alloc_origin origin,
357 int (*cmp) (const void *first, const void *second) = NULL);
359 /* Reverse object map used for every object allocation mapping. */
360 reverse_object_map_t *m_reverse_object_map;
362 private:
363 /* Register overhead of SIZE bytes of ORIGIN type. PTR pointer is allocated
364 in NAME source file, at LINE in source code, in FUNCTION. */
365 T *register_overhead (size_t size, mem_alloc_origin origin, const char *name,
366 int line, const char *function, const void *ptr);
368 /* Allocation location coupled to the description. */
369 mem_location m_location;
371 /* Location to usage mapping. */
372 mem_map_t *m_map;
374 /* Reverse pointer to usage mapping. */
375 reverse_mem_map_t *m_reverse_map;
379 /* Returns true if instance PTR is registered by the memory description. */
381 template <class T>
382 inline bool
383 mem_alloc_description<T>::contains_descriptor_for_instance (const void *ptr)
385 return m_reverse_map->get (ptr);
388 /* Return descriptor for instance PTR. */
390 template <class T>
391 inline T*
392 mem_alloc_description<T>::get_descriptor_for_instance (const void *ptr)
394 return m_reverse_map->get (ptr) ? (*m_reverse_map->get (ptr)).usage : NULL;
398 /* Register memory allocation descriptor for container PTR which is
399 described by a memory LOCATION. */
400 template <class T>
401 inline T*
402 mem_alloc_description<T>::register_descriptor (const void *ptr,
403 mem_location *location)
405 T *usage = NULL;
407 T **slot = m_map->get (location);
408 if (slot)
410 delete location;
411 usage = *slot;
412 usage->m_instances++;
414 else
416 usage = new T ();
417 m_map->put (location, usage);
420 if (!m_reverse_map->get (ptr))
421 m_reverse_map->put (ptr, mem_usage_pair<T> (usage, 0));
423 return usage;
426 /* Register memory allocation descriptor for container PTR. ORIGIN identifies
427 type of container and GGC identifes if the allocation is handled in GGC
428 memory. Each location is identified by file NAME, LINE in source code and
429 FUNCTION name. */
431 template <class T>
432 inline T*
433 mem_alloc_description<T>::register_descriptor (const void *ptr,
434 mem_alloc_origin origin,
435 bool ggc,
436 const char *filename,
437 int line,
438 const char *function)
440 mem_location *l = new mem_location (origin, ggc, filename, line, function);
441 return register_descriptor (ptr, l);
444 /* Register instance overhead identified by PTR pointer. Allocation takes
445 SIZE bytes. */
447 template <class T>
448 inline T*
449 mem_alloc_description<T>::register_instance_overhead (size_t size,
450 const void *ptr)
452 mem_usage_pair <T> *slot = m_reverse_map->get (ptr);
453 if (!slot)
455 /* Due to PCH, it can really happen. */
456 return NULL;
459 T *usage = (*slot).usage;
460 usage->register_overhead (size);
462 return usage;
465 /* For containers (and GGC) where we want to track every instance object,
466 we register allocation of SIZE bytes, identified by PTR pointer, belonging
467 to USAGE descriptor. */
469 template <class T>
470 void
471 mem_alloc_description<T>::register_object_overhead (T *usage, size_t size,
472 const void *ptr)
474 /* In case of GGC, it is possible to have already occupied the memory
475 location. */
476 m_reverse_object_map->put (ptr, std::pair<T *, size_t> (usage, size));
479 /* Register overhead of SIZE bytes of ORIGIN type. PTR pointer is allocated
480 in NAME source file, at LINE in source code, in FUNCTION. */
482 template <class T>
483 inline T*
484 mem_alloc_description<T>::register_overhead (size_t size,
485 mem_alloc_origin origin,
486 const char *filename,
487 int line,
488 const char *function,
489 const void *ptr)
491 T *usage = register_descriptor (ptr, origin, filename, line, function);
492 usage->register_overhead (size);
494 return usage;
497 /* Release PTR pointer of SIZE bytes. */
499 template <class T>
500 inline void
501 mem_alloc_description<T>::release_instance_overhead (void *ptr, size_t size,
502 bool remove_from_map)
504 mem_usage_pair<T> *slot = m_reverse_map->get (ptr);
506 if (!slot)
508 /* Due to PCH, it can really happen. */
509 return;
512 mem_usage_pair<T> usage_pair = *slot;
513 usage_pair.usage->release_overhead (size);
515 if (remove_from_map)
516 m_reverse_map->remove (ptr);
519 /* Release intance object identified by PTR pointer. */
521 template <class T>
522 inline void
523 mem_alloc_description<T>::release_object_overhead (void *ptr)
525 std::pair <T *, size_t> *entry = m_reverse_object_map->get (ptr);
526 if (entry)
528 entry->first->release_overhead (entry->second);
529 m_reverse_object_map->remove (ptr);
533 /* Default contructor. */
535 template <class T>
536 inline
537 mem_alloc_description<T>::mem_alloc_description ()
539 m_map = new mem_map_t (13, false, false);
540 m_reverse_map = new reverse_mem_map_t (13, false, false);
541 m_reverse_object_map = new reverse_object_map_t (13, false, false);
544 /* Default destructor. */
546 template <class T>
547 inline
548 mem_alloc_description<T>::~mem_alloc_description ()
550 for (typename mem_map_t::iterator it = m_map->begin (); it != m_map->end ();
551 ++it)
553 delete (*it).first;
554 delete (*it).second;
557 delete m_map;
558 delete m_reverse_map;
559 delete m_reverse_object_map;
562 /* Get all tracked instances registered by the description. Items are filtered
563 by ORIGIN type, LENGTH is return value where we register the number of
564 elements in the list. If we want to process custom order, CMP comparator
565 can be provided. */
567 template <class T>
568 inline
569 typename mem_alloc_description<T>::mem_list_t *
570 mem_alloc_description<T>::get_list (mem_alloc_origin origin, unsigned *length,
571 int (*cmp) (const void *first, const void *second))
573 /* vec data structure is not used because all vectors generate memory
574 allocation info a it would create a cycle. */
575 size_t element_size = sizeof (mem_list_t);
576 mem_list_t *list = XCNEWVEC (mem_list_t, m_map->elements ());
577 unsigned i = 0;
579 for (typename mem_map_t::iterator it = m_map->begin (); it != m_map->end ();
580 ++it)
581 if ((*it).first->m_origin == origin)
582 list[i++] = std::pair<mem_location*, T*> (*it);
584 qsort (list, i, element_size, cmp == NULL ? T::compare : cmp);
585 *length = i;
587 return list;
590 /* Get sum value for ORIGIN type of allocation for the descriptor. */
592 template <class T>
593 inline T
594 mem_alloc_description<T>::get_sum (mem_alloc_origin origin)
596 unsigned length;
597 mem_list_t *list = get_list (origin, &length);
598 T sum;
600 for (unsigned i = 0; i < length; i++)
601 sum = sum + *list[i].second;
603 XDELETEVEC (list);
605 return sum;
608 /* Dump all tracked instances of type ORIGIN. If we want to process custom
609 order, CMP comparator can be provided. */
611 template <class T>
612 inline void
613 mem_alloc_description<T>::dump (mem_alloc_origin origin,
614 int (*cmp) (const void *first,
615 const void *second))
617 unsigned length;
619 fprintf (stderr, "\n");
621 mem_list_t *list = get_list (origin, &length, cmp);
622 T total = get_sum (origin);
624 T::dump_header (mem_location::get_origin_name (origin));
625 for (int i = length - 1; i >= 0; i--)
626 list[i].second->dump (list[i].first, total);
628 total.dump_footer ();
630 XDELETEVEC (list);
632 fprintf (stderr, "\n");
635 #endif // GCC_MEM_STATS_H