LCOV - code coverage report
Current view: top level - gcc - mem-stats.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 11.3 % 142 16
Test Date: 2026-02-28 14:20:25 Functions: 25.0 % 32 8
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* A memory statistics tracking infrastructure.
       2              :    Copyright (C) 2015-2026 Free Software Foundation, Inc.
       3              :    Contributed by Martin Liska  <mliska@suse.cz>
       4              : 
       5              : This file is part of GCC.
       6              : 
       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.
      11              : 
      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.
      16              : 
      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/>.  */
      20              : 
      21              : #ifndef GCC_MEM_STATS_H
      22              : #define GCC_MEM_STATS_H
      23              : 
      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;
      29              : 
      30              : #define LOCATION_LINE_EXTRA_SPACE 30
      31              : #define LOCATION_LINE_WIDTH       48
      32              : 
      33              : /* Memory allocation location.  */
      34              : class mem_location
      35              : {
      36              : public:
      37              :   /* Default constructor.  */
      38              :   inline
      39      1537502 :   mem_location () {}
      40              : 
      41              :   /* Constructor.  */
      42              :   inline
      43     80238384 :   mem_location (mem_alloc_origin origin, bool ggc,
      44              :                 const char *filename = NULL, int line = 0,
      45     80238384 :                 const char *function = NULL):
      46     80238384 :     m_filename (filename), m_function (function), m_line (line), m_origin
      47     64065324 :     (origin), m_ggc (ggc) {}
      48              : 
      49              :   /* Copy constructor.  */
      50              :   inline
      51              :   mem_location (mem_location &other): m_filename (other.m_filename),
      52              :     m_function (other.m_function), m_line (other.m_line),
      53              :     m_origin (other.m_origin), m_ggc (other.m_ggc) {}
      54              : 
      55              :   /* Compute hash value based on file name, function name and line in
      56              :      source code. As there is just a single pointer registered for every
      57              :      constant that points to e.g. the same file name, we can use hash
      58              :      of the pointer.  */
      59              :   hashval_t
      60              :   hash ()
      61              :   {
      62              :     inchash::hash hash;
      63              : 
      64              :     hash.add_ptr (m_filename);
      65              :     hash.add_ptr (m_function);
      66              :     hash.add_int (m_line);
      67              : 
      68              :     return hash.end ();
      69              :   }
      70              : 
      71              :   /* Return true if the memory location is equal to OTHER.  */
      72              :   int
      73              :   equal (const mem_location &other)
      74              :   {
      75              :     return m_filename == other.m_filename && m_function == other.m_function
      76              :       && m_line == other.m_line;
      77              :   }
      78              : 
      79              :   /* Return trimmed filename for the location.  */
      80              :   inline const char *
      81            0 :   get_trimmed_filename ()
      82              :   {
      83            0 :     const char *s1 = m_filename;
      84            0 :     const char *s2;
      85              : 
      86            0 :     while ((s2 = strstr (s1, "gcc/")))
      87            0 :       s1 = s2 + 4;
      88              : 
      89            0 :     return s1;
      90              :   }
      91              : 
      92              :   inline char *
      93              :   to_string ()
      94              :   {
      95              :     unsigned l = strlen (get_trimmed_filename ()) + strlen (m_function)
      96              :       + LOCATION_LINE_EXTRA_SPACE;
      97              : 
      98              :     char *s = XNEWVEC (char, l);
      99              :     sprintf (s, "%s:%i (%s)", get_trimmed_filename (),
     100              :              m_line, m_function);
     101              : 
     102              :     s[MIN (LOCATION_LINE_WIDTH, l - 1)] = '\0';
     103              : 
     104              :     return s;
     105              :   }
     106              : 
     107              :   /* Return display name associated to ORIGIN type.  */
     108              :   static const char *
     109            0 :   get_origin_name (mem_alloc_origin origin)
     110              :   {
     111            0 :     return mem_alloc_origin_names[(unsigned) origin];
     112              :   }
     113              : 
     114              :   /* File name of source code.  */
     115              :   const char *m_filename;
     116              :   /* Funcation name.  */
     117              :   const char *m_function;
     118              :   /* Line number in source code.  */
     119              :   int m_line;
     120              :   /* Origin type.  */
     121              :   mem_alloc_origin m_origin;
     122              :   /* Flag if used by GGC allocation.  */
     123              :   bool m_ggc;
     124              : };
     125              : 
     126              : /* Memory usage register to a memory location.  */
     127              : class mem_usage
     128              : {
     129              : public:
     130              :   /* Default constructor.  */
     131            0 :   mem_usage (): m_allocated (0), m_times (0), m_peak (0), m_instances (1) {}
     132              : 
     133              :   /* Constructor.  */
     134            0 :   mem_usage (size_t allocated, size_t times, size_t peak, size_t instances = 0):
     135            0 :     m_allocated (allocated), m_times (times), m_peak (peak),
     136            0 :     m_instances (instances) {}
     137              : 
     138              :   /* Register overhead of SIZE bytes.  */
     139              :   inline void
     140            0 :   register_overhead (size_t size)
     141              :   {
     142            0 :     m_allocated += size;
     143            0 :     m_times++;
     144              : 
     145            0 :     if (m_peak < m_allocated)
     146            0 :       m_peak = m_allocated;
     147              :   }
     148              : 
     149              :   /* Release overhead of SIZE bytes.  */
     150              :   inline void
     151            0 :   release_overhead (size_t size)
     152              :   {
     153            0 :     gcc_assert (size <= m_allocated);
     154              : 
     155            0 :     m_allocated -= size;
     156            0 :   }
     157              : 
     158              :   /* Sum the usage with SECOND usage.  */
     159              :   mem_usage
     160              :   operator+ (const mem_usage &second)
     161              :   {
     162              :     return mem_usage (m_allocated + second.m_allocated,
     163              :                       m_times + second.m_times,
     164              :                       m_peak + second.m_peak,
     165              :                       m_instances + second.m_instances);
     166              :   }
     167              : 
     168              :   /* Equality operator.  */
     169              :   inline bool
     170            0 :   operator== (const mem_usage &second) const
     171              :   {
     172            0 :     return (m_allocated == second.m_allocated
     173            0 :             && m_peak == second.m_peak
     174            0 :             && m_times == second.m_times);
     175              :   }
     176              : 
     177              :   /* Comparison operator.  */
     178              :   inline bool
     179            0 :   operator< (const mem_usage &second) const
     180              :   {
     181            0 :     if (*this == second)
     182              :       return false;
     183              : 
     184            0 :     return (m_allocated == second.m_allocated ?
     185            0 :             (m_peak == second.m_peak ? m_times < second.m_times
     186            0 :              : m_peak < second.m_peak) : m_allocated < second.m_allocated);
     187              :   }
     188              : 
     189              :   /* Compare wrapper used by qsort method.  */
     190              :   static int
     191            0 :   compare (const void *first, const void *second)
     192              :   {
     193            0 :     typedef std::pair<mem_location *, mem_usage *> mem_pair_t;
     194              : 
     195            0 :     const mem_pair_t f = *(const mem_pair_t *)first;
     196            0 :     const mem_pair_t s = *(const mem_pair_t *)second;
     197              : 
     198            0 :     if (*f.second == *s.second)
     199              :       return 0;
     200              : 
     201            0 :     return *f.second < *s.second ? 1 : -1;
     202              :   }
     203              : 
     204              :   /* Dump usage coupled to LOC location, where TOTAL is sum of all rows.  */
     205              :   inline void
     206              :   dump (mem_location *loc, const mem_usage &total) const
     207              :   {
     208              :     char *location_string = loc->to_string ();
     209              : 
     210              :     fprintf (stderr, "%-48s " PRsa (9) ":%5.1f%%"
     211              :              PRsa (9) PRsa (9) ":%5.1f%%%10s\n",
     212              :              location_string, SIZE_AMOUNT (m_allocated),
     213              :              get_percent (m_allocated, total.m_allocated),
     214              :              SIZE_AMOUNT (m_peak), SIZE_AMOUNT (m_times),
     215              :              get_percent (m_times, total.m_times), loc->m_ggc ? "ggc" : "heap");
     216              : 
     217              :     free (location_string);
     218              :   }
     219              : 
     220              :   /* Dump footer.  */
     221              :   inline void
     222              :   dump_footer () const
     223              :   {
     224              :     fprintf (stderr, "%s" PRsa (53) PRsa (26) "\n", "Total",
     225              :              SIZE_AMOUNT (m_allocated), SIZE_AMOUNT (m_times));
     226              :   }
     227              : 
     228              :   /* Return fraction of NOMINATOR and DENOMINATOR in percent.  */
     229              :   static inline float
     230              :   get_percent (size_t nominator, size_t denominator)
     231              :   {
     232              :     return denominator == 0 ? 0.0f : nominator * 100.0 / denominator;
     233              :   }
     234              : 
     235              :   /* Print line made of dashes.  */
     236              :   static inline void
     237            0 :   print_dash_line (size_t count = 140)
     238              :   {
     239            0 :     while (count--)
     240            0 :       fputc ('-', stderr);
     241            0 :     fputc ('\n', stderr);
     242            0 :   }
     243              : 
     244              :   /* Dump header with NAME.  */
     245              :   static inline void
     246              :   dump_header (const char *name)
     247              :   {
     248              :     fprintf (stderr, "%-48s %11s%16s%10s%17s\n", name, "Leak", "Peak",
     249              :              "Times", "Type");
     250              :   }
     251              : 
     252              :   /* Current number of allocated bytes.  */
     253              :   size_t m_allocated;
     254              :   /* Number of allocations.  */
     255              :   size_t m_times;
     256              :   /* Peak allocation in bytes.  */
     257              :   size_t m_peak;
     258              :   /* Number of container instances.  */
     259              :   size_t m_instances;
     260              : };
     261              : 
     262              : /* Memory usage pair that connectes memory usage and number
     263              :    of allocated bytes.  */
     264              : template <class T>
     265              : class mem_usage_pair
     266              : {
     267              : public:
     268            0 :   mem_usage_pair (T *usage_, size_t allocated_): usage (usage_),
     269            0 :   allocated (allocated_) {}
     270              : 
     271              :   T *usage;
     272              :   size_t allocated;
     273              : };
     274              : 
     275              : /* Memory allocation description.  */
     276              : template <class T>
     277              : class mem_alloc_description
     278              : {
     279              : public:
     280              :   struct mem_location_hash : nofree_ptr_hash <mem_location>
     281              :   {
     282              :     static hashval_t
     283            0 :     hash (value_type l)
     284              :     {
     285            0 :       inchash::hash hstate;
     286              : 
     287            0 :       hstate.add_ptr ((const void *)l->m_filename);
     288            0 :       hstate.add_ptr (l->m_function);
     289            0 :       hstate.add_int (l->m_line);
     290              : 
     291            0 :       return hstate.end ();
     292              :     }
     293              : 
     294              :     static bool
     295            0 :     equal (value_type l1, value_type l2)
     296              :     {
     297            0 :       return (l1->m_filename == l2->m_filename
     298            0 :               && l1->m_function == l2->m_function
     299            0 :               && l1->m_line == l2->m_line);
     300              :     }
     301              :   };
     302              : 
     303              :   /* Internal class type definitions.  */
     304              :   typedef hash_map <mem_location_hash, T *> mem_map_t;
     305              :   typedef hash_map <const void *, mem_usage_pair<T> > reverse_mem_map_t;
     306              :   typedef hash_map <const void *, std::pair<T *, size_t> > reverse_object_map_t;
     307              :   typedef std::pair <mem_location *, T *> mem_list_t;
     308              : 
     309              :   /* Default contructor.  */
     310              :   mem_alloc_description ();
     311              : 
     312              :   /* Default destructor.  */
     313              :   ~mem_alloc_description ();
     314              : 
     315              :   /* Returns true if instance PTR is registered by the memory description.  */
     316              :   bool contains_descriptor_for_instance (const void *ptr);
     317              : 
     318              :   /* Return descriptor for instance PTR.  */
     319              :   T *get_descriptor_for_instance (const void *ptr);
     320              : 
     321              :   /* Register memory allocation descriptor for container PTR which is
     322              :      described by a memory LOCATION.  */
     323              :   T *register_descriptor (const void *ptr, mem_location *location);
     324              : 
     325              :   /* Register memory allocation descriptor for container PTR.  ORIGIN identifies
     326              :      type of container and GGC identifes if the allocation is handled in GGC
     327              :      memory.  Each location is identified by file NAME, LINE in source code and
     328              :      FUNCTION name.  */
     329              :   T *register_descriptor (const void *ptr, mem_alloc_origin origin,
     330              :                           bool ggc, const char *name, int line,
     331              :                           const char *function);
     332              : 
     333              :   /* Register instance overhead identified by PTR pointer. Allocation takes
     334              :      SIZE bytes.  */
     335              :   T *register_instance_overhead (size_t size, const void *ptr);
     336              : 
     337              :   /* For containers (and GGC) where we want to track every instance object,
     338              :      we register allocation of SIZE bytes, identified by PTR pointer, belonging
     339              :      to USAGE descriptor.  */
     340              :   void register_object_overhead (T *usage, size_t size, const void *ptr);
     341              : 
     342              :   /* Release PTR pointer of SIZE bytes. If REMOVE_FROM_MAP is set to true,
     343              :      remove the instance from reverse map.  Return memory usage that belongs
     344              :      to this memory description.  */
     345              :   T *release_instance_overhead (void *ptr, size_t size,
     346              :                                 bool remove_from_map = false);
     347              : 
     348              :   /* Release instance object identified by PTR pointer.  */
     349              :   void 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);
     356              : 
     357              :   /* Get sum value for ORIGIN type of allocation for the descriptor.  */
     358              :   T get_sum (mem_alloc_origin origin);
     359              : 
     360              :   /* Get all tracked instances registered by the description. Items
     361              :      are filtered by ORIGIN type, LENGTH is return value where we register
     362              :      the number of elements in the list. If we want to process custom order,
     363              :      CMP comparator can be provided.  */
     364              :   mem_list_t *get_list (mem_alloc_origin origin, unsigned *length);
     365              : 
     366              :   /* Dump all tracked instances of type ORIGIN. If we want to process custom
     367              :      order, CMP comparator can be provided.  */
     368              :   void dump (mem_alloc_origin origin);
     369              : 
     370              :   /* Reverse object map used for every object allocation mapping.  */
     371              :   reverse_object_map_t *m_reverse_object_map;
     372              : 
     373              : private:
     374              :   /* Register overhead of SIZE bytes of ORIGIN type. PTR pointer is allocated
     375              :      in NAME source file, at LINE in source code, in FUNCTION.  */
     376              :   T *register_overhead (size_t size, mem_alloc_origin origin, const char *name,
     377              :                         int line, const char *function, const void *ptr);
     378              : 
     379              :   /* Allocation location coupled to the description.  */
     380              :   mem_location m_location;
     381              : 
     382              :   /* Location to usage mapping.  */
     383              :   mem_map_t *m_map;
     384              : 
     385              :   /* Reverse pointer to usage mapping.  */
     386              :   reverse_mem_map_t *m_reverse_map;
     387              : };
     388              : 
     389              : /* Returns true if instance PTR is registered by the memory description.  */
     390              : 
     391              : template <class T>
     392              : inline bool
     393            0 : mem_alloc_description<T>::contains_descriptor_for_instance (const void *ptr)
     394              : {
     395            0 :   return m_reverse_map->get (ptr);
     396              : }
     397              : 
     398              : /* Return descriptor for instance PTR.  */
     399              : 
     400              : template <class T>
     401              : inline T*
     402              : mem_alloc_description<T>::get_descriptor_for_instance (const void *ptr)
     403              : {
     404              :   return m_reverse_map->get (ptr) ? (*m_reverse_map->get (ptr)).usage : NULL;
     405              : }
     406              : 
     407              : /* Register memory allocation descriptor for container PTR which is
     408              :    described by a memory LOCATION.  */
     409              : 
     410              : template <class T>
     411              : inline T*
     412            0 : mem_alloc_description<T>::register_descriptor (const void *ptr,
     413              :                                                mem_location *location)
     414              : {
     415              :   T *usage = NULL;
     416              : 
     417            0 :   T **slot = m_map->get (location);
     418            0 :   if (slot)
     419              :     {
     420            0 :       delete location;
     421            0 :       usage = *slot;
     422            0 :       usage->m_instances++;
     423              :     }
     424              :   else
     425              :     {
     426            0 :       usage = new T ();
     427            0 :       m_map->put (location, usage);
     428              :     }
     429              : 
     430            0 :   if (!m_reverse_map->get (ptr))
     431            0 :     m_reverse_map->put (ptr, mem_usage_pair<T> (usage, 0));
     432              : 
     433            0 :   return usage;
     434              : }
     435              : 
     436              : /* Register memory allocation descriptor for container PTR.  ORIGIN identifies
     437              :    type of container and GGC identifes if the allocation is handled in GGC
     438              :    memory.  Each location is identified by file NAME, LINE in source code and
     439              :    FUNCTION name.  */
     440              : 
     441              : template <class T>
     442              : inline T*
     443            0 : mem_alloc_description<T>::register_descriptor (const void *ptr,
     444              :                                                mem_alloc_origin origin,
     445              :                                                bool ggc,
     446              :                                                const char *filename,
     447              :                                                int line,
     448              :                                                const char *function)
     449              : {
     450            0 :   mem_location *l = new mem_location (origin, ggc, filename, line, function);
     451            0 :   return register_descriptor (ptr, l);
     452              : }
     453              : 
     454              : /* Register instance overhead identified by PTR pointer. Allocation takes
     455              :    SIZE bytes.  */
     456              : 
     457              : template <class T>
     458              : inline T*
     459            0 : mem_alloc_description<T>::register_instance_overhead (size_t size,
     460              :                                                       const void *ptr)
     461              : {
     462            0 :   mem_usage_pair <T> *slot = m_reverse_map->get (ptr);
     463            0 :   if (!slot)
     464              :     {
     465              :       /* Due to PCH, it can really happen.  */
     466              :       return NULL;
     467              :     }
     468              : 
     469            0 :   T *usage = (*slot).usage;
     470            0 :   usage->register_overhead (size);
     471              : 
     472              :   return usage;
     473              : }
     474              : 
     475              : /* For containers (and GGC) where we want to track every instance object,
     476              :    we register allocation of SIZE bytes, identified by PTR pointer, belonging
     477              :    to USAGE descriptor.  */
     478              : 
     479              : template <class T>
     480              : void
     481            0 : mem_alloc_description<T>::register_object_overhead (T *usage, size_t size,
     482              :                                                     const void *ptr)
     483              : {
     484              :   /* In case of GGC, it is possible to have already occupied the memory
     485              :      location.  */
     486            0 :   m_reverse_object_map->put (ptr, std::pair<T *, size_t> (usage, size));
     487              : }
     488              : 
     489              : /* Register overhead of SIZE bytes of ORIGIN type. PTR pointer is allocated
     490              :    in NAME source file, at LINE in source code, in FUNCTION.  */
     491              : 
     492              : template <class T>
     493              : inline T*
     494              : mem_alloc_description<T>::register_overhead (size_t size,
     495              :                                              mem_alloc_origin origin,
     496              :                                              const char *filename,
     497              :                                              int line,
     498              :                                              const char *function,
     499              :                                              const void *ptr)
     500              : {
     501              :   T *usage = register_descriptor (ptr, origin, filename, line, function);
     502              :   usage->register_overhead (size);
     503              : 
     504              :   return usage;
     505              : }
     506              : 
     507              : /* Release PTR pointer of SIZE bytes.  */
     508              : 
     509              : template <class T>
     510              : inline T *
     511            0 : mem_alloc_description<T>::release_instance_overhead (void *ptr, size_t size,
     512              :                                                      bool remove_from_map)
     513              : {
     514            0 :   mem_usage_pair<T> *slot = m_reverse_map->get (ptr);
     515              : 
     516            0 :   if (!slot)
     517              :     {
     518              :       /* Due to PCH, it can really happen.  */
     519              :       return NULL;
     520              :     }
     521              : 
     522            0 :   T *usage = (*slot).usage;
     523            0 :   usage->release_overhead (size);
     524              : 
     525            0 :   if (remove_from_map)
     526            0 :     m_reverse_map->remove (ptr);
     527              : 
     528              :   return usage;
     529              : }
     530              : 
     531              : /* Release instance object identified by PTR pointer.  */
     532              : 
     533              : template <class T>
     534              : inline void
     535            0 : mem_alloc_description<T>::release_object_overhead (void *ptr)
     536              : {
     537            0 :   std::pair <T *, size_t> *entry = m_reverse_object_map->get (ptr);
     538            0 :   entry->first->release_overhead (entry->second);
     539            0 :   m_reverse_object_map->remove (ptr);
     540            0 : }
     541              : 
     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);
     551              : }
     552              : 
     553              : /* Default contructor.  */
     554              : 
     555              : template <class T>
     556              : inline
     557      1537502 : mem_alloc_description<T>::mem_alloc_description ()
     558              : {
     559      1537502 :   m_map = new mem_map_t (13, false, false, false);
     560      1537502 :   m_reverse_map = new reverse_mem_map_t (13, false, false, false);
     561      1537502 :   m_reverse_object_map = new reverse_object_map_t (13, false, false, false);
     562      1537502 : }
     563              : 
     564              : /* Default destructor.  */
     565              : 
     566              : template <class T>
     567              : inline
     568      1537502 : mem_alloc_description<T>::~mem_alloc_description ()
     569              : {
     570      1537502 :   for (typename mem_map_t::iterator it = m_map->begin (); it != m_map->end ();
     571            0 :        ++it)
     572              :     {
     573            0 :       delete (*it).first;
     574            0 :       delete (*it).second;
     575              :     }
     576              : 
     577      3075004 :   delete m_map;
     578      3075004 :   delete m_reverse_map;
     579      3075004 :   delete m_reverse_object_map;
     580      1537502 : }
     581              : 
     582              : /* Get all tracked instances registered by the description. Items are filtered
     583              :    by ORIGIN type, LENGTH is return value where we register the number of
     584              :    elements in the list. If we want to process custom order, CMP comparator
     585              :    can be provided.  */
     586              : 
     587              : template <class T>
     588              : inline
     589              : typename mem_alloc_description<T>::mem_list_t *
     590            0 : mem_alloc_description<T>::get_list (mem_alloc_origin origin, unsigned *length)
     591              : {
     592              :   /* vec data structure is not used because all vectors generate memory
     593              :      allocation info a it would create a cycle.  */
     594            0 :   size_t element_size = sizeof (mem_list_t);
     595            0 :   mem_list_t *list = XCNEWVEC (mem_list_t, m_map->elements ());
     596            0 :   unsigned i = 0;
     597              : 
     598            0 :   for (typename mem_map_t::iterator it = m_map->begin (); it != m_map->end ();
     599            0 :        ++it)
     600            0 :     if ((*it).first->m_origin == origin)
     601            0 :       list[i++] = std::pair<mem_location*, T*> (*it);
     602              : 
     603            0 :   qsort (list, i, element_size, T::compare);
     604            0 :   *length = i;
     605              : 
     606            0 :   return list;
     607              : }
     608              : 
     609              : /* Get sum value for ORIGIN type of allocation for the descriptor.  */
     610              : 
     611              : template <class T>
     612              : inline T
     613            0 : mem_alloc_description<T>::get_sum (mem_alloc_origin origin)
     614              : {
     615              :   unsigned length;
     616            0 :   mem_list_t *list = get_list (origin, &length);
     617            0 :   T sum;
     618              : 
     619            0 :   for (unsigned i = 0; i < length; i++)
     620            0 :     sum = sum + *list[i].second;
     621              : 
     622            0 :   XDELETEVEC (list);
     623              : 
     624            0 :   return sum;
     625              : }
     626              : 
     627              : /* Dump all tracked instances of type ORIGIN. If we want to process custom
     628              :    order, CMP comparator can be provided.  */
     629              : 
     630              : template <class T>
     631              : inline void
     632            0 : mem_alloc_description<T>::dump (mem_alloc_origin origin)
     633              : {
     634              :   unsigned length;
     635              : 
     636            0 :   fprintf (stderr, "\n");
     637              : 
     638            0 :   mem_list_t *list = get_list (origin, &length);
     639            0 :   T total = get_sum (origin);
     640              : 
     641            0 :   T::print_dash_line ();
     642            0 :   T::dump_header (mem_location::get_origin_name (origin));
     643            0 :   T::print_dash_line ();
     644            0 :   for (int i = length - 1; i >= 0; i--)
     645            0 :     list[i].second->dump (list[i].first, total);
     646            0 :   T::print_dash_line ();
     647              : 
     648            0 :   T::dump_header (mem_location::get_origin_name (origin));
     649            0 :   T::print_dash_line ();
     650            0 :   total.dump_footer ();
     651            0 :   T::print_dash_line ();
     652              : 
     653            0 :   XDELETEVEC (list);
     654              : 
     655            0 :   fprintf (stderr, "\n");
     656            0 : }
     657              : 
     658              : #endif // GCC_MEM_STATS_H
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.