LCOV - code coverage report
Current view: top level - gcc - mem-stats.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 11.2 % 143 16
Test Date: 2024-03-23 14:05:01 Functions: 25.0 % 32 8
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* A memory statistics tracking infrastructure.
       2                 :             :    Copyright (C) 2015-2024 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                 :     1546247 :   mem_location () {}
      40                 :             : 
      41                 :             :   /* Constructor.  */
      42                 :             :   inline
      43                 :    76627985 :   mem_location (mem_alloc_origin origin, bool ggc,
      44                 :             :                 const char *filename = NULL, int line = 0,
      45                 :    76627985 :                 const char *function = NULL):
      46                 :    76627985 :     m_filename (filename), m_function (function), m_line (line), m_origin
      47                 :    61082516 :     (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                 :           0 :   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                 :     1546247 : mem_alloc_description<T>::mem_alloc_description ()
     558                 :             : {
     559                 :     1546247 :   m_map = new mem_map_t (13, false, false, false);
     560                 :     1546247 :   m_reverse_map = new reverse_mem_map_t (13, false, false, false);
     561                 :     1546247 :   m_reverse_object_map = new reverse_object_map_t (13, false, false, false);
     562                 :     1546247 : }
     563                 :             : 
     564                 :             : /* Default destructor.  */
     565                 :             : 
     566                 :             : template <class T>
     567                 :             : inline
     568                 :     1546247 : mem_alloc_description<T>::~mem_alloc_description ()
     569                 :             : {
     570                 :     1546247 :   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                 :     3092494 :   delete m_map;
     578                 :     3092494 :   delete m_reverse_map;
     579                 :     3092494 :   delete m_reverse_object_map;
     580                 :     1546247 : }
     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.0-1

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.