Fix copyright years.
[official-gcc.git] / gcc / mem-stats.h
blobac472315fd39c48f409b38eb7356a18cc1e536c3
1 #ifndef GCC_MEM_STATS_H
2 #define GCC_MEM_STATS_H
4 #include "hash-map-traits.h"
5 #include "inchash.h"
6 #include "mem-stats-traits.h"
7 #include "vec.h"
9 /* Forward declaration. */
10 template<typename Key, typename Value,
11 typename Traits = default_hashmap_traits>
12 class hash_map;
14 /* Memory allocation location. */
15 struct mem_location
17 /* Default constructor. */
18 inline mem_location () {}
20 /* Constructor. */
21 inline mem_location (const char *filename, const char *function, int line,
22 mem_alloc_origin origin, bool ggc):
23 m_filename (filename), m_function (function), m_line (line), m_origin
24 (origin), m_ggc (ggc) {}
26 /* Compute hash value based on file name, function name and line in
27 source code. As there is just a single pointer registered for every
28 constant that points to e.g. the same file name, we can use hash
29 of the pointer. */
30 hashval_t hash ()
32 inchash::hash hash;
34 hash.add_ptr (m_filename);
35 hash.add_ptr (m_function);
36 hash.add_int (m_line);
38 return hash.end ();
41 /* Return true if the memory location is equal to OTHER. */
42 int equal (mem_location &other)
44 return m_filename == other.m_filename && m_function == other.m_function
45 && m_line == other.m_line;
48 /* Return trimmed filename for the location. */
49 inline const char *get_trimmed_filename ()
51 const char *s1 = m_filename;
52 const char *s2;
54 while ((s2 = strstr (s1, "gcc/")))
55 s1 = s2 + 4;
57 return s1;
60 /* Return display name associated to ORIGIN type. */
61 static const char *get_origin_name (mem_alloc_origin origin)
63 return mem_alloc_origin_names[(unsigned) origin];
66 /* File name of source code. */
67 const char *m_filename;
68 /* Funcation name. */
69 const char *m_function;
70 /* Line number in source code. */
71 int m_line;
72 /* Origin type. */
73 mem_alloc_origin m_origin;
74 /* Flag if used by GGC allocation. */
75 bool m_ggc;
78 /* Memory usage register to a memory location. */
79 struct mem_usage
81 /* Default constructor. */
82 mem_usage (): m_allocated (0), m_times (0), m_peak (0) {}
84 /* Constructor. */
85 mem_usage (size_t allocated, size_t times, size_t peak):
86 m_allocated (allocated), m_times (times), m_peak (peak) {}
88 /* Register overhead of SIZE bytes. */
89 inline void register_overhead (size_t size)
91 m_allocated += size;
92 m_times++;
94 if (m_peak < m_allocated)
95 m_peak = m_allocated;
98 /* Release overhead of SIZE bytes. */
99 inline void release_overhead (size_t size)
101 gcc_assert (size <= m_allocated);
103 m_allocated -= size;
106 /* Sum the usage with SECOND usage. */
107 mem_usage operator+ (const mem_usage &second)
109 return mem_usage (m_allocated + second.m_allocated,
110 m_times + second.m_times,
111 m_peak + second.m_peak);
114 /* Comparison operator. */
115 inline bool operator< (const mem_usage &second) const
117 return (m_allocated == second.m_allocated ?
118 (m_peak == second.m_peak ? m_times < second.m_times
119 : m_peak < second.m_peak) : m_allocated < second.m_allocated);
122 /* Compare wrapper used by qsort method. */
123 static int compare (const void *first, const void *second)
125 typedef std::pair<mem_location *, mem_usage *> mem_pair_t;
127 const mem_pair_t f = *(const mem_pair_t *)first;
128 const mem_pair_t s = *(const mem_pair_t *)second;
130 return (*f.second) < (*s.second);
133 /* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */
134 inline void dump (mem_location *loc, mem_usage &total) const
136 char s[4096];
137 sprintf (s, "%s:%i (%s)", loc->get_trimmed_filename (),
138 loc->m_line, loc->m_function);
140 s[48] = '\0';
142 fprintf (stderr, "%-48s %10li:%5.1f%%%10li%10li:%5.1f%%%10s\n", s,
143 (long)m_allocated, get_percent (m_allocated, total.m_allocated),
144 (long)m_peak, (long)m_times,
145 get_percent (m_times, total.m_times), loc->m_ggc ? "ggc" : "heap");
148 /* Dump footer. */
149 inline void dump_footer ()
151 print_dash_line ();
152 fprintf (stderr, "%s%54li%27li\n", "Total", (long)m_allocated,
153 (long)m_times);
154 print_dash_line ();
157 /* Return fraction of NOMINATOR and DENOMINATOR in percent. */
158 static inline float get_percent (size_t nominator, size_t denominator)
160 return denominator == 0 ? 0.0f : nominator * 100.0 / denominator;
163 /* Print line made of dashes. */
164 static inline void print_dash_line ()
166 fprintf (stderr, "%s\n", std::string (128, '-').c_str ());
169 /* Dump header with NAME. */
170 static inline void dump_header (const char *name)
172 fprintf (stderr, "%-48s %11s%16s%10s%17s\n", name, "Leak", "Peak",
173 "Times", "Type");
174 print_dash_line ();
177 /* Current number of allocated bytes. */
178 size_t m_allocated;
179 /* Number of allocations. */
180 size_t m_times;
181 /* Peak allocation in bytes. */
182 size_t m_peak;
185 /* Memory usage pair that connectes memory usage and number
186 of allocated bytes. */
187 template <class T>
188 struct mem_usage_pair
190 mem_usage_pair (T *usage_, size_t allocated_): usage (usage_),
191 allocated (allocated_) {}
193 T *usage;
194 size_t allocated;
197 /* Memory allocation description. */
198 template <class T>
199 class mem_alloc_description
201 public:
202 struct mem_alloc_hashmap_traits: default_hashmap_traits
204 static hashval_t
205 hash (const mem_location *l)
207 inchash::hash hstate;
209 hstate.add_ptr ((const void *)l->m_filename);
210 hstate.add_ptr (l->m_function);
211 hstate.add_int (l->m_line);
213 return hstate.end ();
216 static bool
217 equal_keys (const mem_location *l1, const mem_location *l2)
219 return l1->m_filename == l2->m_filename
220 && l1->m_function == l2->m_function
221 && l1->m_line == l2->m_line;
225 /* Internal class type definitions. */
226 typedef hash_map <mem_location *, T *, mem_alloc_hashmap_traits> mem_map_t;
227 typedef hash_map <const void *, mem_usage_pair<T>, default_hashmap_traits>
228 reverse_mem_map_t;
229 typedef hash_map <const void *, std::pair<T *, size_t> > reverse_object_map_t;
230 typedef std::pair <mem_location *, T *> mem_list_t;
232 /* Default contructor. */
233 mem_alloc_description ();
235 /* Default destructor. */
236 ~mem_alloc_description ();
238 /* Returns true if instance PTR is registered by the memory description. */
239 bool contains_descriptor_for_instance (const void *ptr);
241 /* Return descriptor for instance PTR. */
242 T *get_descriptor_for_instance (const void *ptr);
244 /* Register memory allocation descriptor for container PTR. ORIGIN identifies
245 type of container and GGC identifes if the allocation is handled in GGC
246 memory. Each location is identified by file NAME, LINE in source code and
247 FUNCTION name. */
248 T *register_descriptor (const void *ptr, mem_alloc_origin origin,
249 bool ggc, const char *name, int line,
250 const char *function);
252 /* Register instance overhead identified by PTR pointer. Allocation takes
253 SIZE bytes. */
254 T *register_instance_overhead (size_t size, const void *ptr);
256 /* For containers (and GGC) where we want to track every instance object,
257 we register allocation of SIZE bytes, identified by PTR pointer, belonging
258 to USAGE descriptor. */
259 void register_object_overhead (T *usage, size_t size, const void *ptr);
261 /* Release PTR pointer of SIZE bytes. If REMOVE_FROM_MAP is set to true,
262 remove the instance from reverse map. */
263 void release_instance_overhead (void *ptr, size_t size,
264 bool remove_from_map = false);
266 /* Release intance object identified by PTR pointer. */
267 void release_object_overhead (void *ptr);
269 /* Get sum value for ORIGIN type of allocation for the descriptor. */
270 T get_sum (mem_alloc_origin origin);
272 /* Get all tracked instances registered by the description. Items
273 are filtered by ORIGIN type, LENGTH is return value where we register
274 the number of elements in the list. If we want to process custom order,
275 CMP comparator can be provided. */
276 mem_list_t *get_list (mem_alloc_origin origin, unsigned *length,
277 int (*cmp) (const void *first, const void *second)
278 = NULL);
280 /* Dump all tracked instances of type ORIGIN. If we want to process custom
281 order, CMP comparator can be provided. */
282 void dump (mem_alloc_origin origin,
283 int (*cmp) (const void *first, const void *second) = NULL);
285 /* Reverse object map used for every object allocation mapping. */
286 reverse_object_map_t *m_reverse_object_map;
288 private:
289 /* Register overhead of SIZE bytes of ORIGIN type. PTR pointer is allocated
290 in NAME source file, at LINE in source code, in FUNCTION. */
291 T *register_overhead (size_t size, mem_alloc_origin origin, const char *name,
292 int line, const char *function, const void *ptr);
294 /* Allocation location coupled to the description. */
295 mem_location m_location;
297 /* Location to usage mapping. */
298 mem_map_t *m_map;
300 /* Reverse pointer to usage mapping. */
301 reverse_mem_map_t *m_reverse_map;
304 #include "hash-map.h"
306 /* Returns true if instance PTR is registered by the memory description. */
308 template <class T>
309 inline bool
310 mem_alloc_description<T>::contains_descriptor_for_instance (const void *ptr)
312 return m_reverse_map->get (ptr);
315 /* Return descriptor for instance PTR. */
317 template <class T>
318 inline T*
319 mem_alloc_description<T>::get_descriptor_for_instance (const void *ptr)
321 return m_reverse_map->get (ptr) ? (*m_reverse_map->get (ptr)).usage : NULL;
324 /* Register memory allocation descriptor for container PTR. ORIGIN identifies
325 type of container and GGC identifes if the allocation is handled in GGC
326 memory. Each location is identified by file NAME, LINE in source code and
327 FUNCTION name. */
329 template <class T>
330 inline T*
331 mem_alloc_description<T>::register_descriptor (const void *ptr,
332 mem_alloc_origin origin,
333 bool ggc,
334 const char *filename,
335 int line,
336 const char *function)
338 mem_location *l = new mem_location (filename, function, line, origin, ggc);
339 T *usage = NULL;
341 T **slot = m_map->get (l);
342 if (slot)
344 delete l;
345 usage = *slot;
347 else
349 usage = new T ();
350 m_map->put (l, usage);
353 if (!m_reverse_map->get (ptr))
354 m_reverse_map->put (ptr, mem_usage_pair<T> (usage, 0));
356 return usage;
359 /* Register instance overhead identified by PTR pointer. Allocation takes
360 SIZE bytes. */
362 template <class T>
363 inline T*
364 mem_alloc_description<T>::register_instance_overhead (size_t size,
365 const void *ptr)
367 mem_usage_pair <T> *slot = m_reverse_map->get (ptr);
368 if (!slot)
370 /* Due to PCH, it can really happen. */
371 return NULL;
374 T *usage = (*slot).usage;
375 usage->register_overhead (size);
377 return usage;
380 /* For containers (and GGC) where we want to track every instance object,
381 we register allocation of SIZE bytes, identified by PTR pointer, belonging
382 to USAGE descriptor. */
384 template <class T>
385 void
386 mem_alloc_description<T>::register_object_overhead (T *usage, size_t size,
387 const void *ptr)
389 /* In case of GGC, it is possible to have already occupied the memory
390 location. */
391 m_reverse_object_map->put (ptr, std::pair<T *, size_t> (usage, size));
394 /* Register overhead of SIZE bytes of ORIGIN type. PTR pointer is allocated
395 in NAME source file, at LINE in source code, in FUNCTION. */
397 template <class T>
398 inline T*
399 mem_alloc_description<T>::register_overhead (size_t size,
400 mem_alloc_origin origin,
401 const char *filename,
402 int line,
403 const char *function,
404 const void *ptr)
406 T *usage = register_descriptor (ptr, origin, filename, line, function);
407 usage->register_overhead (size);
409 return usage;
412 /* Release PTR pointer of SIZE bytes. */
414 template <class T>
415 inline void
416 mem_alloc_description<T>::release_instance_overhead (void *ptr, size_t size,
417 bool remove_from_map)
419 mem_usage_pair<T> *slot = m_reverse_map->get (ptr);
421 if (!slot)
423 /* Due to PCH, it can really happen. */
424 return;
427 mem_usage_pair<T> usage_pair = *slot;
428 usage_pair.usage->release_overhead (size);
430 if (remove_from_map)
431 m_reverse_map->remove (ptr);
434 /* Release intance object identified by PTR pointer. */
436 template <class T>
437 inline void
438 mem_alloc_description<T>::release_object_overhead (void *ptr)
440 std::pair <T *, size_t> *entry = m_reverse_object_map->get (ptr);
441 if (entry)
443 entry->first->release_overhead (entry->second);
444 m_reverse_object_map->remove (ptr);
448 /* Default contructor. */
450 template <class T>
451 inline
452 mem_alloc_description<T>::mem_alloc_description ()
454 m_map = new mem_map_t (13, false, false);
455 m_reverse_map = new reverse_mem_map_t (13, false, false);
456 m_reverse_object_map = new reverse_object_map_t (13, false, false);
459 /* Default destructor. */
461 template <class T>
462 inline
463 mem_alloc_description<T>::~mem_alloc_description ()
465 for (typename mem_map_t::iterator it = m_map->begin (); it != m_map->end ();
466 ++it)
468 delete (*it).first;
469 delete (*it).second;
472 delete m_map;
473 delete m_reverse_map;
474 delete m_reverse_object_map;
477 /* Get all tracked instances registered by the description. Items are filtered
478 by ORIGIN type, LENGTH is return value where we register the number of
479 elements in the list. If we want to process custom order, CMP comparator
480 can be provided. */
482 template <class T>
483 inline
484 typename mem_alloc_description<T>::mem_list_t *
485 mem_alloc_description<T>::get_list (mem_alloc_origin origin, unsigned *length,
486 int (*cmp) (const void *first, const void *second))
488 /* vec data structure is not used because all vectors generate memory
489 allocation info a it would create a cycle. */
490 size_t element_size = sizeof (mem_list_t);
491 mem_list_t *list = XCNEWVEC (mem_list_t, m_map->elements ());
492 unsigned i = 0;
494 for (typename mem_map_t::iterator it = m_map->begin (); it != m_map->end ();
495 ++it)
496 if ((*it).first->m_origin == origin)
497 list[i++] = std::pair<mem_location*, T*> (*it);
499 qsort (list, i, element_size, cmp == NULL ? T::compare : cmp);
500 *length = i;
502 return list;
505 /* Get sum value for ORIGIN type of allocation for the descriptor. */
507 template <class T>
508 inline T
509 mem_alloc_description<T>::get_sum (mem_alloc_origin origin)
511 unsigned length;
512 mem_list_t *list = get_list (origin, &length);
513 T sum;
515 for (unsigned i = 0; i < length; i++)
516 sum = sum + *list[i].second;
518 XDELETEVEC (list);
520 return sum;
523 /* Dump all tracked instances of type ORIGIN. If we want to process custom
524 order, CMP comparator can be provided. */
526 template <class T>
527 inline void
528 mem_alloc_description<T>::dump (mem_alloc_origin origin,
529 int (*cmp) (const void *first,
530 const void *second))
532 unsigned length;
534 fprintf (stderr, "\n");
536 mem_list_t *list = get_list (origin, &length, cmp);
537 T total = get_sum (origin);
539 T::dump_header (mem_location::get_origin_name (origin));
540 for (int i = length - 1; i >= 0; i--)
541 list[i].second->dump (list[i].first, total);
543 total.dump_footer ();
545 XDELETEVEC (list);
547 fprintf (stderr, "\n");
550 #endif // GCC_MEM_STATS_H