comparison gcc/mem-stats.h @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
comparison
equal deleted inserted replaced
131:84e7813d76e9 145:1830386684a0
1 /* A memory statistics tracking infrastructure. 1 /* A memory statistics tracking infrastructure.
2 Copyright (C) 2015-2018 Free Software Foundation, Inc. 2 Copyright (C) 2015-2020 Free Software Foundation, Inc.
3 Contributed by Martin Liska <mliska@suse.cz> 3 Contributed by Martin Liska <mliska@suse.cz>
4 4
5 This file is part of GCC. 5 This file is part of GCC.
6 6
7 GCC is free software; you can redistribute it and/or modify it under 7 GCC is free software; you can redistribute it and/or modify it under
29 29
30 #define LOCATION_LINE_EXTRA_SPACE 30 30 #define LOCATION_LINE_EXTRA_SPACE 30
31 #define LOCATION_LINE_WIDTH 48 31 #define LOCATION_LINE_WIDTH 48
32 32
33 /* Memory allocation location. */ 33 /* Memory allocation location. */
34 struct mem_location 34 class mem_location
35 { 35 {
36 public:
36 /* Default constructor. */ 37 /* Default constructor. */
37 inline 38 inline
38 mem_location () {} 39 mem_location () {}
39 40
40 /* Constructor. */ 41 /* Constructor. */
121 /* Flag if used by GGC allocation. */ 122 /* Flag if used by GGC allocation. */
122 bool m_ggc; 123 bool m_ggc;
123 }; 124 };
124 125
125 /* Memory usage register to a memory location. */ 126 /* Memory usage register to a memory location. */
126 struct mem_usage 127 class mem_usage
127 { 128 {
129 public:
128 /* Default constructor. */ 130 /* Default constructor. */
129 mem_usage (): m_allocated (0), m_times (0), m_peak (0), m_instances (1) {} 131 mem_usage (): m_allocated (0), m_times (0), m_peak (0), m_instances (1) {}
130 132
131 /* Constructor. */ 133 /* Constructor. */
132 mem_usage (size_t allocated, size_t times, size_t peak, size_t instances = 0): 134 mem_usage (size_t allocated, size_t times, size_t peak, size_t instances = 0):
203 inline void 205 inline void
204 dump (mem_location *loc, mem_usage &total) const 206 dump (mem_location *loc, mem_usage &total) const
205 { 207 {
206 char *location_string = loc->to_string (); 208 char *location_string = loc->to_string ();
207 209
208 fprintf (stderr, "%-48s %10" PRIu64 ":%5.1f%%" 210 fprintf (stderr, "%-48s " PRsa (9) ":%5.1f%%"
209 "%10" PRIu64 "%10" PRIu64 ":%5.1f%%%10s\n", 211 PRsa (9) PRsa (9) ":%5.1f%%%10s\n",
210 location_string, (uint64_t)m_allocated, 212 location_string, SIZE_AMOUNT (m_allocated),
211 get_percent (m_allocated, total.m_allocated), 213 get_percent (m_allocated, total.m_allocated),
212 (uint64_t)m_peak, (uint64_t)m_times, 214 SIZE_AMOUNT (m_peak), SIZE_AMOUNT (m_times),
213 get_percent (m_times, total.m_times), loc->m_ggc ? "ggc" : "heap"); 215 get_percent (m_times, total.m_times), loc->m_ggc ? "ggc" : "heap");
214 216
215 free (location_string); 217 free (location_string);
216 } 218 }
217 219
218 /* Dump footer. */ 220 /* Dump footer. */
219 inline void 221 inline void
220 dump_footer () const 222 dump_footer () const
221 { 223 {
222 print_dash_line (); 224 fprintf (stderr, "%s" PRsa (53) PRsa (26) "\n", "Total",
223 fprintf (stderr, "%s%54" PRIu64 "%27" PRIu64 "\n", "Total", 225 SIZE_AMOUNT (m_allocated), SIZE_AMOUNT (m_times));
224 (uint64_t)m_allocated, (uint64_t)m_times);
225 print_dash_line ();
226 } 226 }
227 227
228 /* Return fraction of NOMINATOR and DENOMINATOR in percent. */ 228 /* Return fraction of NOMINATOR and DENOMINATOR in percent. */
229 static inline float 229 static inline float
230 get_percent (size_t nominator, size_t denominator) 230 get_percent (size_t nominator, size_t denominator)
245 static inline void 245 static inline void
246 dump_header (const char *name) 246 dump_header (const char *name)
247 { 247 {
248 fprintf (stderr, "%-48s %11s%16s%10s%17s\n", name, "Leak", "Peak", 248 fprintf (stderr, "%-48s %11s%16s%10s%17s\n", name, "Leak", "Peak",
249 "Times", "Type"); 249 "Times", "Type");
250 print_dash_line ();
251 } 250 }
252 251
253 /* Current number of allocated bytes. */ 252 /* Current number of allocated bytes. */
254 size_t m_allocated; 253 size_t m_allocated;
255 /* Number of allocations. */ 254 /* Number of allocations. */
261 }; 260 };
262 261
263 /* Memory usage pair that connectes memory usage and number 262 /* Memory usage pair that connectes memory usage and number
264 of allocated bytes. */ 263 of allocated bytes. */
265 template <class T> 264 template <class T>
266 struct mem_usage_pair 265 class mem_usage_pair
267 { 266 {
267 public:
268 mem_usage_pair (T *usage_, size_t allocated_): usage (usage_), 268 mem_usage_pair (T *usage_, size_t allocated_): usage (usage_),
269 allocated (allocated_) {} 269 allocated (allocated_) {}
270 270
271 T *usage; 271 T *usage;
272 size_t allocated; 272 size_t allocated;
280 struct mem_location_hash : nofree_ptr_hash <mem_location> 280 struct mem_location_hash : nofree_ptr_hash <mem_location>
281 { 281 {
282 static hashval_t 282 static hashval_t
283 hash (value_type l) 283 hash (value_type l)
284 { 284 {
285 inchash::hash hstate; 285 inchash::hash hstate;
286 286
287 hstate.add_ptr ((const void *)l->m_filename); 287 hstate.add_ptr ((const void *)l->m_filename);
288 hstate.add_ptr (l->m_function); 288 hstate.add_ptr (l->m_function);
289 hstate.add_int (l->m_line); 289 hstate.add_int (l->m_line);
290 290
291 return hstate.end (); 291 return hstate.end ();
292 } 292 }
293 293
294 static bool 294 static bool
295 equal (value_type l1, value_type l2) 295 equal (value_type l1, value_type l2)
296 { 296 {
297 return l1->m_filename == l2->m_filename 297 return (l1->m_filename == l2->m_filename
298 && l1->m_function == l2->m_function 298 && l1->m_function == l2->m_function
299 && l1->m_line == l2->m_line; 299 && l1->m_line == l2->m_line);
300 } 300 }
301 }; 301 };
302 302
303 /* Internal class type definitions. */ 303 /* Internal class type definitions. */
304 typedef hash_map <mem_location_hash, T *> mem_map_t; 304 typedef hash_map <mem_location_hash, T *> mem_map_t;
311 311
312 /* Default destructor. */ 312 /* Default destructor. */
313 ~mem_alloc_description (); 313 ~mem_alloc_description ();
314 314
315 /* Returns true if instance PTR is registered by the memory description. */ 315 /* Returns true if instance PTR is registered by the memory description. */
316 bool 316 bool contains_descriptor_for_instance (const void *ptr);
317 contains_descriptor_for_instance (const void *ptr);
318 317
319 /* Return descriptor for instance PTR. */ 318 /* Return descriptor for instance PTR. */
320 T * 319 T *get_descriptor_for_instance (const void *ptr);
321 get_descriptor_for_instance (const void *ptr);
322 320
323 /* Register memory allocation descriptor for container PTR which is 321 /* Register memory allocation descriptor for container PTR which is
324 described by a memory LOCATION. */ 322 described by a memory LOCATION. */
325 T * 323 T *register_descriptor (const void *ptr, mem_location *location);
326 register_descriptor (const void *ptr, mem_location *location);
327 324
328 /* Register memory allocation descriptor for container PTR. ORIGIN identifies 325 /* Register memory allocation descriptor for container PTR. ORIGIN identifies
329 type of container and GGC identifes if the allocation is handled in GGC 326 type of container and GGC identifes if the allocation is handled in GGC
330 memory. Each location is identified by file NAME, LINE in source code and 327 memory. Each location is identified by file NAME, LINE in source code and
331 FUNCTION name. */ 328 FUNCTION name. */
332 T * 329 T *register_descriptor (const void *ptr, mem_alloc_origin origin,
333 register_descriptor (const void *ptr, mem_alloc_origin origin,
334 bool ggc, const char *name, int line, 330 bool ggc, const char *name, int line,
335 const char *function); 331 const char *function);
336 332
337 /* Register instance overhead identified by PTR pointer. Allocation takes 333 /* Register instance overhead identified by PTR pointer. Allocation takes
338 SIZE bytes. */ 334 SIZE bytes. */
339 T * 335 T *register_instance_overhead (size_t size, const void *ptr);
340 register_instance_overhead (size_t size, const void *ptr);
341 336
342 /* For containers (and GGC) where we want to track every instance object, 337 /* For containers (and GGC) where we want to track every instance object,
343 we register allocation of SIZE bytes, identified by PTR pointer, belonging 338 we register allocation of SIZE bytes, identified by PTR pointer, belonging
344 to USAGE descriptor. */ 339 to USAGE descriptor. */
345 void 340 void register_object_overhead (T *usage, size_t size, const void *ptr);
346 register_object_overhead (T *usage, size_t size, const void *ptr);
347 341
348 /* Release PTR pointer of SIZE bytes. If REMOVE_FROM_MAP is set to true, 342 /* Release PTR pointer of SIZE bytes. If REMOVE_FROM_MAP is set to true,
349 remove the instance from reverse map. */ 343 remove the instance from reverse map. Return memory usage that belongs
350 void 344 to this memory description. */
351 release_instance_overhead (void *ptr, size_t size, 345 T *release_instance_overhead (void *ptr, size_t size,
352 bool remove_from_map = false); 346 bool remove_from_map = false);
353 347
354 /* Release intance object identified by PTR pointer. */ 348 /* Release instance object identified by PTR pointer. */
355 void 349 void release_object_overhead (void *ptr);
356 release_object_overhead (void *ptr); 350
351 /* Unregister a memory allocation descriptor registered with
352 register_descriptor (remove from reverse map), unless it is
353 unregistered through release_instance_overhead with
354 REMOVE_FROM_MAP = true. */
355 void unregister_descriptor (void *ptr);
357 356
358 /* Get sum value for ORIGIN type of allocation for the descriptor. */ 357 /* Get sum value for ORIGIN type of allocation for the descriptor. */
359 T 358 T get_sum (mem_alloc_origin origin);
360 get_sum (mem_alloc_origin origin);
361 359
362 /* Get all tracked instances registered by the description. Items 360 /* Get all tracked instances registered by the description. Items
363 are filtered by ORIGIN type, LENGTH is return value where we register 361 are filtered by ORIGIN type, LENGTH is return value where we register
364 the number of elements in the list. If we want to process custom order, 362 the number of elements in the list. If we want to process custom order,
365 CMP comparator can be provided. */ 363 CMP comparator can be provided. */
366 mem_list_t * 364 mem_list_t *get_list (mem_alloc_origin origin, unsigned *length);
367 get_list (mem_alloc_origin origin, unsigned *length,
368 int (*cmp) (const void *first, const void *second) = NULL);
369 365
370 /* Dump all tracked instances of type ORIGIN. If we want to process custom 366 /* Dump all tracked instances of type ORIGIN. If we want to process custom
371 order, CMP comparator can be provided. */ 367 order, CMP comparator can be provided. */
372 void dump (mem_alloc_origin origin, 368 void dump (mem_alloc_origin origin);
373 int (*cmp) (const void *first, const void *second) = NULL);
374 369
375 /* Reverse object map used for every object allocation mapping. */ 370 /* Reverse object map used for every object allocation mapping. */
376 reverse_object_map_t *m_reverse_object_map; 371 reverse_object_map_t *m_reverse_object_map;
377 372
378 private: 373 private:
389 384
390 /* Reverse pointer to usage mapping. */ 385 /* Reverse pointer to usage mapping. */
391 reverse_mem_map_t *m_reverse_map; 386 reverse_mem_map_t *m_reverse_map;
392 }; 387 };
393 388
394
395 /* Returns true if instance PTR is registered by the memory description. */ 389 /* Returns true if instance PTR is registered by the memory description. */
396 390
397 template <class T> 391 template <class T>
398 inline bool 392 inline bool
399 mem_alloc_description<T>::contains_descriptor_for_instance (const void *ptr) 393 mem_alloc_description<T>::contains_descriptor_for_instance (const void *ptr)
408 mem_alloc_description<T>::get_descriptor_for_instance (const void *ptr) 402 mem_alloc_description<T>::get_descriptor_for_instance (const void *ptr)
409 { 403 {
410 return m_reverse_map->get (ptr) ? (*m_reverse_map->get (ptr)).usage : NULL; 404 return m_reverse_map->get (ptr) ? (*m_reverse_map->get (ptr)).usage : NULL;
411 } 405 }
412 406
413 407 /* Register memory allocation descriptor for container PTR which is
414 /* Register memory allocation descriptor for container PTR which is 408 described by a memory LOCATION. */
415 described by a memory LOCATION. */ 409
416 template <class T> 410 template <class T>
417 inline T* 411 inline T*
418 mem_alloc_description<T>::register_descriptor (const void *ptr, 412 mem_alloc_description<T>::register_descriptor (const void *ptr,
419 mem_location *location) 413 mem_location *location)
420 { 414 {
511 } 505 }
512 506
513 /* Release PTR pointer of SIZE bytes. */ 507 /* Release PTR pointer of SIZE bytes. */
514 508
515 template <class T> 509 template <class T>
516 inline void 510 inline T *
517 mem_alloc_description<T>::release_instance_overhead (void *ptr, size_t size, 511 mem_alloc_description<T>::release_instance_overhead (void *ptr, size_t size,
518 bool remove_from_map) 512 bool remove_from_map)
519 { 513 {
520 mem_usage_pair<T> *slot = m_reverse_map->get (ptr); 514 mem_usage_pair<T> *slot = m_reverse_map->get (ptr);
521 515
522 if (!slot) 516 if (!slot)
523 { 517 {
524 /* Due to PCH, it can really happen. */ 518 /* Due to PCH, it can really happen. */
525 return; 519 return NULL;
526 } 520 }
527 521
528 mem_usage_pair<T> usage_pair = *slot; 522 T *usage = (*slot).usage;
529 usage_pair.usage->release_overhead (size); 523 usage->release_overhead (size);
530 524
531 if (remove_from_map) 525 if (remove_from_map)
532 m_reverse_map->remove (ptr); 526 m_reverse_map->remove (ptr);
533 } 527
534 528 return usage;
535 /* Release intance object identified by PTR pointer. */ 529 }
530
531 /* Release instance object identified by PTR pointer. */
536 532
537 template <class T> 533 template <class T>
538 inline void 534 inline void
539 mem_alloc_description<T>::release_object_overhead (void *ptr) 535 mem_alloc_description<T>::release_object_overhead (void *ptr)
540 { 536 {
541 std::pair <T *, size_t> *entry = m_reverse_object_map->get (ptr); 537 std::pair <T *, size_t> *entry = m_reverse_object_map->get (ptr);
542 if (entry) 538 entry->first->release_overhead (entry->second);
543 { 539 m_reverse_object_map->remove (ptr);
544 entry->first->release_overhead (entry->second); 540 }
545 m_reverse_object_map->remove (ptr); 541
546 } 542 /* Unregister a memory allocation descriptor registered with
543 register_descriptor (remove from reverse map), unless it is
544 unregistered through release_instance_overhead with
545 REMOVE_FROM_MAP = true. */
546 template <class T>
547 inline void
548 mem_alloc_description<T>::unregister_descriptor (void *ptr)
549 {
550 m_reverse_map->remove (ptr);
547 } 551 }
548 552
549 /* Default contructor. */ 553 /* Default contructor. */
550 554
551 template <class T> 555 template <class T>
552 inline 556 inline
553 mem_alloc_description<T>::mem_alloc_description () 557 mem_alloc_description<T>::mem_alloc_description ()
554 { 558 {
555 m_map = new mem_map_t (13, false, false); 559 m_map = new mem_map_t (13, false, false, false);
556 m_reverse_map = new reverse_mem_map_t (13, false, false); 560 m_reverse_map = new reverse_mem_map_t (13, false, false, false);
557 m_reverse_object_map = new reverse_object_map_t (13, false, false); 561 m_reverse_object_map = new reverse_object_map_t (13, false, false, false);
558 } 562 }
559 563
560 /* Default destructor. */ 564 /* Default destructor. */
561 565
562 template <class T> 566 template <class T>
581 can be provided. */ 585 can be provided. */
582 586
583 template <class T> 587 template <class T>
584 inline 588 inline
585 typename mem_alloc_description<T>::mem_list_t * 589 typename mem_alloc_description<T>::mem_list_t *
586 mem_alloc_description<T>::get_list (mem_alloc_origin origin, unsigned *length, 590 mem_alloc_description<T>::get_list (mem_alloc_origin origin, unsigned *length)
587 int (*cmp) (const void *first, const void *second))
588 { 591 {
589 /* vec data structure is not used because all vectors generate memory 592 /* vec data structure is not used because all vectors generate memory
590 allocation info a it would create a cycle. */ 593 allocation info a it would create a cycle. */
591 size_t element_size = sizeof (mem_list_t); 594 size_t element_size = sizeof (mem_list_t);
592 mem_list_t *list = XCNEWVEC (mem_list_t, m_map->elements ()); 595 mem_list_t *list = XCNEWVEC (mem_list_t, m_map->elements ());
595 for (typename mem_map_t::iterator it = m_map->begin (); it != m_map->end (); 598 for (typename mem_map_t::iterator it = m_map->begin (); it != m_map->end ();
596 ++it) 599 ++it)
597 if ((*it).first->m_origin == origin) 600 if ((*it).first->m_origin == origin)
598 list[i++] = std::pair<mem_location*, T*> (*it); 601 list[i++] = std::pair<mem_location*, T*> (*it);
599 602
600 qsort (list, i, element_size, cmp == NULL ? T::compare : cmp); 603 qsort (list, i, element_size, T::compare);
601 *length = i; 604 *length = i;
602 605
603 return list; 606 return list;
604 } 607 }
605 608
624 /* Dump all tracked instances of type ORIGIN. If we want to process custom 627 /* Dump all tracked instances of type ORIGIN. If we want to process custom
625 order, CMP comparator can be provided. */ 628 order, CMP comparator can be provided. */
626 629
627 template <class T> 630 template <class T>
628 inline void 631 inline void
629 mem_alloc_description<T>::dump (mem_alloc_origin origin, 632 mem_alloc_description<T>::dump (mem_alloc_origin origin)
630 int (*cmp) (const void *first,
631 const void *second))
632 { 633 {
633 unsigned length; 634 unsigned length;
634 635
635 fprintf (stderr, "\n"); 636 fprintf (stderr, "\n");
636 637
637 mem_list_t *list = get_list (origin, &length, cmp); 638 mem_list_t *list = get_list (origin, &length);
638 T total = get_sum (origin); 639 T total = get_sum (origin);
639 640
641 T::print_dash_line ();
640 T::dump_header (mem_location::get_origin_name (origin)); 642 T::dump_header (mem_location::get_origin_name (origin));
643 T::print_dash_line ();
641 for (int i = length - 1; i >= 0; i--) 644 for (int i = length - 1; i >= 0; i--)
642 list[i].second->dump (list[i].first, total); 645 list[i].second->dump (list[i].first, total);
643 646 T::print_dash_line ();
647
648 T::dump_header (mem_location::get_origin_name (origin));
649 T::print_dash_line ();
644 total.dump_footer (); 650 total.dump_footer ();
651 T::print_dash_line ();
645 652
646 XDELETEVEC (list); 653 XDELETEVEC (list);
647 654
648 fprintf (stderr, "\n"); 655 fprintf (stderr, "\n");
649 } 656 }