LCOV - code coverage report
Current view: top level - gcc - mem-stats.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 2.2 % 135 3
Test Date: 2026-08-22 16:33:35 Functions: 0.0 % 28 0
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            0 :   mem_location () {}
      40              : 
      41              :   /* Constructor.  */
      42              :   inline
      43     81806775 :   mem_location (mem_alloc_origin origin, bool ggc,
      44              :                 const char *filename = NULL, int line = 0,
      45              :                 const char *function = NULL):
      46     81806775 :     m_filename (filename), m_function (function), m_line (line), m_origin
      47     65167726 :     (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              :   /* Function 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 connects 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              : 
     280              :   /* Constructor is private to enforce singleton.  */
     281              :   mem_alloc_description ();
     282              : 
     283              :   /* Destruction is not allowed, since we might be tracking
     284              :      static objects with undefined destruction order.  */
     285              :   ~mem_alloc_description () = delete;
     286              : 
     287              : public:
     288              : 
     289              :   template<mem_alloc_origin>
     290            0 :   static auto &instance ()
     291              :   {
     292            0 :     static const auto self = new mem_alloc_description;
     293            0 :     return *self;
     294              :   }
     295              : 
     296              :   struct mem_location_hash : nofree_ptr_hash <mem_location>
     297              :   {
     298              :     static hashval_t
     299            0 :     hash (value_type l)
     300              :     {
     301            0 :       inchash::hash hstate;
     302              : 
     303            0 :       hstate.add_ptr ((const void *)l->m_filename);
     304            0 :       hstate.add_ptr (l->m_function);
     305            0 :       hstate.add_int (l->m_line);
     306              : 
     307            0 :       return hstate.end ();
     308              :     }
     309              : 
     310              :     static bool
     311            0 :     equal (value_type l1, value_type l2)
     312              :     {
     313            0 :       return (l1->m_filename == l2->m_filename
     314            0 :               && l1->m_function == l2->m_function
     315            0 :               && l1->m_line == l2->m_line);
     316              :     }
     317              :   };
     318              : 
     319              :   /* Internal class type definitions.  */
     320              :   typedef hash_map <mem_location_hash, T *> mem_map_t;
     321              :   typedef hash_map <const void *, mem_usage_pair<T> > reverse_mem_map_t;
     322              :   typedef hash_map <const void *, std::pair<T *, size_t> > reverse_object_map_t;
     323              :   typedef std::pair <mem_location *, T *> mem_list_t;
     324              : 
     325              : 
     326              :   /* Returns true if instance PTR is registered by the memory description.  */
     327              :   bool contains_descriptor_for_instance (const void *ptr);
     328              : 
     329              :   /* Return descriptor for instance PTR.  */
     330              :   T *get_descriptor_for_instance (const void *ptr);
     331              : 
     332              :   /* Register memory allocation descriptor for container PTR which is
     333              :      described by a memory LOCATION.  */
     334              :   T *register_descriptor (const void *ptr, mem_location *location);
     335              : 
     336              :   /* Register memory allocation descriptor for container PTR.  ORIGIN identifies
     337              :      type of container and GGC identifies if the allocation is handled in GGC
     338              :      memory.  Each location is identified by file NAME, LINE in source code and
     339              :      FUNCTION name.  */
     340              :   T *register_descriptor (const void *ptr, mem_alloc_origin origin,
     341              :                           bool ggc, const char *name, int line,
     342              :                           const char *function);
     343              : 
     344              :   /* Register instance overhead identified by PTR pointer. Allocation takes
     345              :      SIZE bytes.  */
     346              :   T *register_instance_overhead (size_t size, const void *ptr);
     347              : 
     348              :   /* For containers (and GGC) where we want to track every instance object,
     349              :      we register allocation of SIZE bytes, identified by PTR pointer, belonging
     350              :      to USAGE descriptor.  */
     351              :   void register_object_overhead (T *usage, size_t size, const void *ptr);
     352              : 
     353              :   /* Release PTR pointer of SIZE bytes. If REMOVE_FROM_MAP is set to true,
     354              :      remove the instance from reverse map.  Return memory usage that belongs
     355              :      to this memory description.  */
     356              :   T *release_instance_overhead (void *ptr, size_t size,
     357              :                                 bool remove_from_map = false);
     358              : 
     359              :   /* Release instance object identified by PTR pointer.  */
     360              :   void release_object_overhead (void *ptr);
     361              : 
     362              :   /* Unregister a memory allocation descriptor registered with
     363              :      register_descriptor (remove from reverse map), unless it is
     364              :      unregistered through release_instance_overhead with
     365              :      REMOVE_FROM_MAP = true.  */
     366              :   void unregister_descriptor (void *ptr);
     367              : 
     368              :   /* Get sum value for ORIGIN type of allocation for the descriptor.  */
     369              :   T get_sum (mem_alloc_origin origin);
     370              : 
     371              :   /* Get all tracked instances registered by the description. Items
     372              :      are filtered by ORIGIN type, LENGTH is return value where we register
     373              :      the number of elements in the list. If we want to process custom order,
     374              :      CMP comparator can be provided.  */
     375              :   mem_list_t *get_list (mem_alloc_origin origin, unsigned *length);
     376              : 
     377              :   /* Dump all tracked instances of type ORIGIN. If we want to process custom
     378              :      order, CMP comparator can be provided.  */
     379              :   void dump (mem_alloc_origin origin);
     380              : 
     381              :   /* Reverse object map used for every object allocation mapping.  */
     382              :   reverse_object_map_t *m_reverse_object_map;
     383              : 
     384              : private:
     385              :   /* Register overhead of SIZE bytes of ORIGIN type. PTR pointer is allocated
     386              :      in NAME source file, at LINE in source code, in FUNCTION.  */
     387              :   T *register_overhead (size_t size, mem_alloc_origin origin, const char *name,
     388              :                         int line, const char *function, const void *ptr);
     389              : 
     390              :   /* Allocation location coupled to the description.  */
     391              :   mem_location m_location;
     392              : 
     393              :   /* Location to usage mapping.  */
     394              :   mem_map_t *m_map;
     395              : 
     396              :   /* Reverse pointer to usage mapping.  */
     397              :   reverse_mem_map_t *m_reverse_map;
     398              : };
     399              : 
     400              : /* Returns true if instance PTR is registered by the memory description.  */
     401              : 
     402              : template <class T>
     403              : inline bool
     404            0 : mem_alloc_description<T>::contains_descriptor_for_instance (const void *ptr)
     405              : {
     406            0 :   return m_reverse_map->get (ptr);
     407              : }
     408              : 
     409              : /* Return descriptor for instance PTR.  */
     410              : 
     411              : template <class T>
     412              : inline T*
     413              : mem_alloc_description<T>::get_descriptor_for_instance (const void *ptr)
     414              : {
     415              :   return m_reverse_map->get (ptr) ? (*m_reverse_map->get (ptr)).usage : NULL;
     416              : }
     417              : 
     418              : /* Register memory allocation descriptor for container PTR which is
     419              :    described by a memory LOCATION.  */
     420              : 
     421              : template <class T>
     422              : inline T*
     423            0 : mem_alloc_description<T>::register_descriptor (const void *ptr,
     424              :                                                mem_location *location)
     425              : {
     426              :   T *usage = NULL;
     427              : 
     428            0 :   T **slot = m_map->get (location);
     429            0 :   if (slot)
     430              :     {
     431            0 :       delete location;
     432            0 :       usage = *slot;
     433            0 :       usage->m_instances++;
     434              :     }
     435              :   else
     436              :     {
     437            0 :       usage = new T ();
     438            0 :       m_map->put (location, usage);
     439              :     }
     440              : 
     441            0 :   if (!m_reverse_map->get (ptr))
     442            0 :     m_reverse_map->put (ptr, mem_usage_pair<T> (usage, 0));
     443              : 
     444            0 :   return usage;
     445              : }
     446              : 
     447              : /* Register memory allocation descriptor for container PTR.  ORIGIN identifies
     448              :    type of container and GGC identifies if the allocation is handled in GGC
     449              :    memory.  Each location is identified by file NAME, LINE in source code and
     450              :    FUNCTION name.  */
     451              : 
     452              : template <class T>
     453              : inline T*
     454            0 : mem_alloc_description<T>::register_descriptor (const void *ptr,
     455              :                                                mem_alloc_origin origin,
     456              :                                                bool ggc,
     457              :                                                const char *filename,
     458              :                                                int line,
     459              :                                                const char *function)
     460              : {
     461            0 :   mem_location *l = new mem_location (origin, ggc, filename, line, function);
     462            0 :   return register_descriptor (ptr, l);
     463              : }
     464              : 
     465              : /* Register instance overhead identified by PTR pointer. Allocation takes
     466              :    SIZE bytes.  */
     467              : 
     468              : template <class T>
     469              : inline T*
     470            0 : mem_alloc_description<T>::register_instance_overhead (size_t size,
     471              :                                                       const void *ptr)
     472              : {
     473            0 :   mem_usage_pair <T> *slot = m_reverse_map->get (ptr);
     474            0 :   if (!slot)
     475              :     {
     476              :       /* Due to PCH, it can really happen.  */
     477              :       return NULL;
     478              :     }
     479              : 
     480            0 :   T *usage = (*slot).usage;
     481            0 :   usage->register_overhead (size);
     482              : 
     483              :   return usage;
     484              : }
     485              : 
     486              : /* For containers (and GGC) where we want to track every instance object,
     487              :    we register allocation of SIZE bytes, identified by PTR pointer, belonging
     488              :    to USAGE descriptor.  */
     489              : 
     490              : template <class T>
     491              : void
     492            0 : mem_alloc_description<T>::register_object_overhead (T *usage, size_t size,
     493              :                                                     const void *ptr)
     494              : {
     495              :   /* In case of GGC, it is possible to have already occupied the memory
     496              :      location.  */
     497            0 :   m_reverse_object_map->put (ptr, std::pair<T *, size_t> (usage, size));
     498              : }
     499              : 
     500              : /* Register overhead of SIZE bytes of ORIGIN type. PTR pointer is allocated
     501              :    in NAME source file, at LINE in source code, in FUNCTION.  */
     502              : 
     503              : template <class T>
     504              : inline T*
     505              : mem_alloc_description<T>::register_overhead (size_t size,
     506              :                                              mem_alloc_origin origin,
     507              :                                              const char *filename,
     508              :                                              int line,
     509              :                                              const char *function,
     510              :                                              const void *ptr)
     511              : {
     512              :   T *usage = register_descriptor (ptr, origin, filename, line, function);
     513              :   usage->register_overhead (size);
     514              : 
     515              :   return usage;
     516              : }
     517              : 
     518              : /* Release PTR pointer of SIZE bytes.  */
     519              : 
     520              : template <class T>
     521              : inline T *
     522            0 : mem_alloc_description<T>::release_instance_overhead (void *ptr, size_t size,
     523              :                                                      bool remove_from_map)
     524              : {
     525            0 :   mem_usage_pair<T> *slot = m_reverse_map->get (ptr);
     526              : 
     527            0 :   if (!slot)
     528              :     {
     529              :       /* Due to PCH, it can really happen.  */
     530              :       return NULL;
     531              :     }
     532              : 
     533            0 :   T *usage = (*slot).usage;
     534            0 :   usage->release_overhead (size);
     535              : 
     536            0 :   if (remove_from_map)
     537            0 :     m_reverse_map->remove (ptr);
     538              : 
     539              :   return usage;
     540              : }
     541              : 
     542              : /* Release instance object identified by PTR pointer.  */
     543              : 
     544              : template <class T>
     545              : inline void
     546            0 : mem_alloc_description<T>::release_object_overhead (void *ptr)
     547              : {
     548            0 :   std::pair <T *, size_t> *entry = m_reverse_object_map->get (ptr);
     549            0 :   if (!entry)
     550              :     return;
     551            0 :   entry->first->release_overhead (entry->second);
     552            0 :   m_reverse_object_map->remove (ptr);
     553              : }
     554              : 
     555              : /* Unregister a memory allocation descriptor registered with
     556              :    register_descriptor (remove from reverse map), unless it is
     557              :    unregistered through release_instance_overhead with
     558              :    REMOVE_FROM_MAP = true.  */
     559              : template <class T>
     560              : inline void
     561              : mem_alloc_description<T>::unregister_descriptor (void *ptr)
     562              : {
     563              :   m_reverse_map->remove (ptr);
     564              : }
     565              : 
     566              : /* Default constructor.  */
     567              : 
     568              : template <class T>
     569              : inline
     570            0 : mem_alloc_description<T>::mem_alloc_description ()
     571              : {
     572              :   /* Note it is important to pass false for the 4th argument (GATHER_MEM_STATS)
     573              :      to avoid infinite recursion in instance ().  */
     574            0 :   m_map = new mem_map_t (13, false, false, false);
     575            0 :   m_reverse_map = new reverse_mem_map_t (13, false, false, false);
     576            0 :   m_reverse_object_map = new reverse_object_map_t (13, false, false, false);
     577            0 : }
     578              : 
     579              : /* Get all tracked instances registered by the description. Items are filtered
     580              :    by ORIGIN type, LENGTH is return value where we register the number of
     581              :    elements in the list. If we want to process custom order, CMP comparator
     582              :    can be provided.  */
     583              : 
     584              : template <class T>
     585              : inline
     586              : typename mem_alloc_description<T>::mem_list_t *
     587            0 : mem_alloc_description<T>::get_list (mem_alloc_origin origin, unsigned *length)
     588              : {
     589              :   /* vec data structure is not used because all vectors generate memory
     590              :      allocation info a it would create a cycle.  */
     591            0 :   size_t element_size = sizeof (mem_list_t);
     592            0 :   mem_list_t *list = XCNEWVEC (mem_list_t, m_map->elements ());
     593            0 :   unsigned i = 0;
     594              : 
     595            0 :   for (typename mem_map_t::iterator it = m_map->begin (); it != m_map->end ();
     596            0 :        ++it)
     597            0 :     if ((*it).first->m_origin == origin)
     598            0 :       list[i++] = std::pair<mem_location*, T*> (*it);
     599              : 
     600            0 :   qsort (list, i, element_size, T::compare);
     601            0 :   *length = i;
     602              : 
     603            0 :   return list;
     604              : }
     605              : 
     606              : /* Get sum value for ORIGIN type of allocation for the descriptor.  */
     607              : 
     608              : template <class T>
     609              : inline T
     610            0 : mem_alloc_description<T>::get_sum (mem_alloc_origin origin)
     611              : {
     612              :   unsigned length;
     613            0 :   mem_list_t *list = get_list (origin, &length);
     614            0 :   T sum;
     615              : 
     616            0 :   for (unsigned i = 0; i < length; i++)
     617            0 :     sum = sum + *list[i].second;
     618              : 
     619            0 :   XDELETEVEC (list);
     620              : 
     621            0 :   return sum;
     622              : }
     623              : 
     624              : /* Dump all tracked instances of type ORIGIN. If we want to process custom
     625              :    order, CMP comparator can be provided.  */
     626              : 
     627              : template <class T>
     628              : inline void
     629            0 : mem_alloc_description<T>::dump (mem_alloc_origin origin)
     630              : {
     631              :   unsigned length;
     632              : 
     633            0 :   fprintf (stderr, "\n");
     634              : 
     635            0 :   mem_list_t *list = get_list (origin, &length);
     636            0 :   T total = get_sum (origin);
     637              : 
     638            0 :   T::print_dash_line ();
     639            0 :   T::dump_header (mem_location::get_origin_name (origin));
     640            0 :   T::print_dash_line ();
     641            0 :   for (int i = length - 1; i >= 0; i--)
     642            0 :     list[i].second->dump (list[i].first, total);
     643            0 :   T::print_dash_line ();
     644              : 
     645            0 :   T::dump_header (mem_location::get_origin_name (origin));
     646            0 :   T::print_dash_line ();
     647            0 :   total.dump_footer ();
     648            0 :   T::print_dash_line ();
     649              : 
     650            0 :   XDELETEVEC (list);
     651              : 
     652            0 :   fprintf (stderr, "\n");
     653            0 : }
     654              : 
     655              : #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.