LCOV - code coverage report
Current view: top level - gcc - hash-map.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 116 116
Test Date: 2026-02-28 14:20:25 Functions: 90.8 % 687 624
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* A type-safe hash map.
       2              :    Copyright (C) 2014-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : 
      21              : #ifndef hash_map_h
      22              : #define hash_map_h
      23              : 
      24              : /* Class hash_map is a hash-value based container mapping objects of
      25              :    KeyId type to those of the Value type.
      26              :    Both KeyId and Value may be non-trivial (non-POD) types provided
      27              :    a suitabe Traits class.  A few default Traits specializations are
      28              :    provided for basic types such as integers, pointers, and std::pair.
      29              :    Inserted elements are value-initialized either to zero for POD types
      30              :    or by invoking their default ctor.  Removed elements are destroyed
      31              :    by invoking their dtor.   On hash_map destruction all elements are
      32              :    removed.  Objects of hash_map type are copy-constructible but not
      33              :    assignable.  */
      34              : 
      35              : const size_t default_hash_map_size = 13;
      36              : template<typename KeyId, typename Value,
      37              :          typename Traits /* = simple_hashmap_traits<default_hash_traits<Key>,
      38              :                                                     Value> */>
      39    709017391 : class GTY((user)) hash_map
      40              : {
      41              :   typedef typename Traits::key_type Key;
      42      7985955 :   struct hash_entry
      43              :   {
      44              :     Key m_key;
      45              :     Value m_value;
      46              : 
      47              :     typedef hash_entry value_type;
      48              :     typedef Key compare_type;
      49              : 
      50  >13483*10^7 :     static hashval_t hash (const hash_entry &e)
      51              :       {
      52  >13524*10^7 :         return Traits::hash (e.m_key);
      53              :       }
      54              : 
      55  >15740*10^7 :     static bool equal (const hash_entry &a, const Key &b)
      56              :         {
      57  >15779*10^7 :           return Traits::equal_keys (a.m_key, b);
      58              :         }
      59              : 
      60    590888440 :     static void remove (hash_entry &e) { Traits::remove (e); }
      61              : 
      62     23244877 :     static void mark_deleted (hash_entry &e) { Traits::mark_deleted (e); }
      63              : 
      64  >20341*10^7 :     static bool is_deleted (const hash_entry &e)
      65              :       {
      66  >20307*10^7 :         return Traits::is_deleted (e);
      67              :       }
      68              : 
      69              :     static const bool empty_zero_p = Traits::empty_zero_p;
      70   1681750392 :     static void mark_empty (hash_entry &e) { Traits::mark_empty (e); }
      71  >72148*10^7 :     static bool is_empty (const hash_entry &e) { return Traits::is_empty (e); }
      72              : 
      73   1028577156 :     static void ggc_mx (hash_entry &e)
      74              :       {
      75    113220647 :         gt_ggc_mx (e.m_key);
      76   1020159749 :         gt_ggc_mx (e.m_value);
      77     93613049 :       }
      78              : 
      79     17423609 :     static void ggc_maybe_mx (hash_entry &e)
      80              :       {
      81              :         if (Traits::maybe_mx)
      82    936854201 :           ggc_mx (e);
      83    934657611 :       }
      84              : 
      85       262863 :     static void pch_nx (hash_entry &e)
      86              :       {
      87        25494 :         gt_pch_nx (e.m_key);
      88       262836 :         gt_pch_nx (e.m_value);
      89       262863 :       }
      90              : 
      91       262863 :     static void pch_nx (hash_entry &e, gt_pointer_operator op, void *c)
      92              :       {
      93        50961 :         pch_nx_helper (e.m_key, op, c);
      94       288303 :         pch_nx_helper (e.m_value, op, c);
      95       262863 :       }
      96              : 
      97     93745006 :     static int keep_cache_entry (hash_entry &e)
      98              :       {
      99     93745006 :         return ggc_marked_p (e.m_key);
     100              :       }
     101              : 
     102              :   private:
     103              :     template<typename T>
     104              :     static void
     105       235916 :       pch_nx_helper (T &x, gt_pointer_operator op, void *cookie)
     106              :         {
     107       235916 :           gt_pch_nx (&x, op, cookie);
     108              :         }
     109              : 
     110              :     template<typename T>
     111              :       static void
     112        52414 :       pch_nx_helper (T *&x, gt_pointer_operator op, void *cookie)
     113              :         {
     114        26947 :           op (&x, NULL, cookie);
     115              :         }
     116              : 
     117              :     /* The overloads below should match those in ggc.h.  */
     118              : #define DEFINE_PCH_HELPER(T)                    \
     119              :     static void pch_nx_helper (T, gt_pointer_operator, void *) { }
     120              : 
     121              :     DEFINE_PCH_HELPER (bool);
     122              :     DEFINE_PCH_HELPER (char);
     123              :     DEFINE_PCH_HELPER (signed char);
     124              :     DEFINE_PCH_HELPER (unsigned char);
     125              :     DEFINE_PCH_HELPER (short);
     126              :     DEFINE_PCH_HELPER (unsigned short);
     127              :     DEFINE_PCH_HELPER (int);
     128              :     DEFINE_PCH_HELPER (unsigned int);
     129              :     DEFINE_PCH_HELPER (long);
     130              :     DEFINE_PCH_HELPER (unsigned long);
     131              :     DEFINE_PCH_HELPER (long long);
     132              :     DEFINE_PCH_HELPER (unsigned long long);
     133              : 
     134              : #undef DEFINE_PCH_HELPER
     135              :   };
     136              : 
     137              : public:
     138   1307141122 :   explicit hash_map (size_t n = default_hash_map_size, bool ggc = false,
     139              :                      bool sanitize_eq_and_hash = true,
     140              :                      bool gather_mem_stats = GATHER_STATISTICS
     141              :                      CXX_MEM_STAT_INFO)
     142   1300914050 :     : m_table (n, ggc, sanitize_eq_and_hash, gather_mem_stats,
     143              :                HASH_MAP_ORIGIN PASS_MEM_STAT)
     144              :   {
     145      1492116 :   }
     146              : 
     147      6536007 :   explicit hash_map (const hash_map &h, bool ggc = false,
     148              :                      bool sanitize_eq_and_hash = true,
     149              :                      bool gather_mem_stats = GATHER_STATISTICS
     150              :                      CXX_MEM_STAT_INFO)
     151      6536007 :     : m_table (h.m_table, ggc, sanitize_eq_and_hash, gather_mem_stats,
     152              :                HASH_MAP_ORIGIN PASS_MEM_STAT) {}
     153              : 
     154              :   /* Create a hash_map in ggc memory.  */
     155      2749597 :   static hash_map *create_ggc (size_t size = default_hash_map_size,
     156              :                                bool gather_mem_stats = GATHER_STATISTICS
     157              :                                CXX_MEM_STAT_INFO)
     158              :     {
     159      2749597 :       hash_map *map = ggc_alloc<hash_map> ();
     160      2749597 :       new (map) hash_map (size, true, true, gather_mem_stats PASS_MEM_STAT);
     161      2749597 :       return map;
     162              :     }
     163              : 
     164              :   /* If key k isn't already in the map add key k with value v to the map, and
     165              :      return false.  Otherwise set the value of the entry for key k to be v and
     166              :      return true.  */
     167              : 
     168   7183600670 :   bool put (const Key &k, const Value &v)
     169              :     {
     170   7183600670 :       hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
     171              :                                                    INSERT);
     172   7183600670 :       bool ins = Traits::is_empty (*e);
     173   7183600670 :       if (ins)
     174              :         {
     175   6591199478 :           e->m_key = k;
     176   6591199478 :           new ((void *)&e->m_value) Value (v);
     177   6591199478 :           gcc_checking_assert (!Traits::is_empty (*e)
     178              :                                && !Traits::is_deleted (*e));
     179              :         }
     180              :       else
     181    592401192 :         e->m_value = v;
     182              : 
     183   7183600670 :       return !ins;
     184              :     }
     185              : 
     186              :   /* If the passed in key is in the map return pointer to its value
     187              :      otherwise NULL.  */
     188              : 
     189  27043128442 :   Value *get (const Key &k)
     190              :     {
     191  27043128442 :       hash_entry &e = m_table.find_with_hash (k, Traits::hash (k));
     192  27015420753 :       return Traits::is_empty (e) ? NULL : &e.m_value;
     193              :     }
     194              : 
     195              :   /* Return a reference to the value for the passed in key, creating the entry
     196              :      if it doesn't already exist.  If existed is not NULL then it is set to
     197              :      false if the key was not previously in the map, and true otherwise.  */
     198              : 
     199   2677018731 :   Value &get_or_insert (const Key &k, bool *existed = NULL)
     200              :     {
     201   2677018731 :       hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
     202              :                                                    INSERT);
     203   2677063943 :       bool ins = Traits::is_empty (*e);
     204   2676785089 :       if (ins)
     205              :         {
     206   1789701481 :           e->m_key = k;
     207   1789701481 :           new ((void *)&e->m_value) Value ();
     208   1789889911 :           gcc_checking_assert (!Traits::is_empty (*e)
     209              :                                && !Traits::is_deleted (*e));
     210              :         }
     211              : 
     212   2677018731 :       if (existed != NULL)
     213   2529732869 :         *existed = !ins;
     214              : 
     215   2677018731 :       return e->m_value;
     216              :     }
     217              : 
     218    212219287 :   void remove (const Key &k)
     219              :     {
     220    212219287 :       m_table.remove_elt_with_hash (k, Traits::hash (k));
     221    178898660 :     }
     222              : 
     223              :   /* Call the call back on each pair of key and value with the passed in
     224              :      arg until either the call back returns false or all pairs have been seen.
     225              :      The traversal is unordered.  */
     226              : 
     227              :   template<typename Arg, bool (*f)(const typename Traits::key_type &,
     228              :                                    const Value &, Arg)>
     229     73128420 :   void traverse (Arg a) const
     230              :     {
     231    267547617 :       for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
     232    461966814 :            iter != m_table.end (); ++iter)
     233    194419197 :         if (!f ((*iter).m_key, (*iter).m_value, a))
     234              :           break;
     235     73128420 :     }
     236              : 
     237              :   template<typename Arg, bool (*f)(const typename Traits::key_type &,
     238              :                                    Value *, Arg)>
     239        29444 :   void traverse (Arg a) const
     240              :     {
     241        97684 :       for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
     242       165924 :            iter != m_table.end (); ++iter)
     243        68240 :         if (!f ((*iter).m_key, &(*iter).m_value, a))
     244              :           break;
     245        29444 :     }
     246              : 
     247     27201733 :   size_t elements () const { return m_table.elements (); }
     248              : 
     249    507986513 :   void empty () { m_table.empty(); }
     250              : 
     251              :   /* Return true when there are no elements in this hash map.  */
     252      5088921 :   bool is_empty () const { return m_table.is_empty (); }
     253              : 
     254              :   class iterator
     255              :   {
     256              :   public:
     257    497013640 :     explicit iterator (const typename hash_table<hash_entry>::iterator &iter) :
     258    121907342 :       m_iter (iter) {}
     259              : 
     260    942454399 :     iterator &operator++ ()
     261              :     {
     262    942454399 :       ++m_iter;
     263    900452386 :       return *this;
     264              :     }
     265              : 
     266              :     /* Can't use std::pair here, because GCC before 4.3 don't handle
     267              :        std::pair where template parameters are references well.
     268              :        See PR86739.  */
     269              :     class reference_pair {
     270              :     public:
     271              :       const Key &first;
     272              :       Value &second;
     273              : 
     274    988762765 :       reference_pair (const Key &key, Value &value) : first (key), second (value) {}
     275              : 
     276              :       template <typename K, typename V>
     277       216927 :       operator std::pair<K, V> () const { return std::pair<K, V> (first, second); }
     278              :     };
     279              : 
     280    988762765 :     reference_pair operator* ()
     281              :     {
     282    988762765 :       hash_entry &e = *m_iter;
     283    474944676 :       return reference_pair (e.m_key, e.m_value);
     284              :     }
     285              : 
     286              :     bool operator== (const iterator &other) const
     287              :     {
     288              :       return m_iter == other.m_iter;
     289              :     }
     290              : 
     291   1064361741 :     bool operator != (const iterator &other) const
     292              :     {
     293   1185842890 :       return m_iter != other.m_iter;
     294              :     }
     295              : 
     296              :   private:
     297              :     typename hash_table<hash_entry>::iterator m_iter;
     298              :   };
     299              : 
     300              :   /* Standard iterator retrieval methods.  */
     301              : 
     302    121907342 :   iterator  begin () const { return iterator (m_table.begin ()); }
     303    602800554 :   iterator end () const { return iterator (m_table.end ()); }
     304              : 
     305              : private:
     306              : 
     307              :   template<typename T, typename U, typename V> friend void gt_ggc_mx (hash_map<T, U, V> *);
     308              :   template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *);
     309              :   template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);
     310              :   template<typename T, typename U, typename V> friend void gt_cleare_cache (hash_map<T, U, V> *);
     311              : 
     312              :   hash_table<hash_entry> m_table;
     313              : };
     314              : 
     315              : /* ggc marking routines.  */
     316              : 
     317              : template<typename K, typename V, typename H>
     318              : inline void
     319      6350016 : gt_ggc_mx (hash_map<K, V, H> *h)
     320              : {
     321      6350016 :   gt_ggc_mx (&h->m_table);
     322      5827149 : }
     323              : 
     324              : template<typename K, typename V, typename H>
     325              : inline void
     326          670 : gt_pch_nx (hash_map<K, V, H> *h)
     327              : {
     328          670 :   gt_pch_nx (&h->m_table);
     329          670 : }
     330              : 
     331              : template<typename K, typename V, typename H>
     332              : inline void
     333       750561 : gt_cleare_cache (hash_map<K, V, H> *h)
     334              : {
     335       643365 :   if (h)
     336       208373 :     gt_cleare_cache (&h->m_table);
     337              : }
     338              : 
     339              : template<typename K, typename V, typename H>
     340              : inline void
     341          670 : gt_pch_nx (hash_map<K, V, H> *h, gt_pointer_operator op, void *cookie)
     342              : {
     343          670 :   op (&h->m_table.m_entries, NULL, cookie);
     344          670 : }
     345              : 
     346              : enum hm_alloc { hm_heap = false, hm_ggc = true };
     347              : template<bool ggc, typename K, typename V, typename H>
     348              : inline hash_map<K,V,H> *
     349    324196860 : hash_map_maybe_create (hash_map<K,V,H> *&h,
     350              :                        size_t size = default_hash_map_size)
     351              : {
     352    324196860 :   if (!h)
     353              :     {
     354              :       if (ggc)
     355       349501 :         h = hash_map<K,V,H>::create_ggc (size);
     356              :       else
     357              :         h = new hash_map<K,V,H> (size);
     358              :     }
     359    324196860 :   return h;
     360              : }
     361              : 
     362              : /* Like h->get, but handles null h.  */
     363              : template<typename K, typename V, typename H>
     364              : inline V*
     365   2364745570 : hash_map_safe_get (hash_map<K,V,H> *h, const K& k)
     366              : {
     367   2364745570 :   return h ? h->get (k) : NULL;
     368              : }
     369              : 
     370              : /* Like h->get, but handles null h.  */
     371              : template<bool ggc, typename K, typename V, typename H>
     372              : inline V&
     373     76748463 : hash_map_safe_get_or_insert (hash_map<K,V,H> *&h, const K& k, bool *e = NULL,
     374              :                              size_t size = default_hash_map_size)
     375              : {
     376     76748463 :   return hash_map_maybe_create<ggc> (h, size)->get_or_insert (k, e);
     377              : }
     378              : 
     379              : /* Like h->put, but handles null h.  */
     380              : template<bool ggc, typename K, typename V, typename H>
     381              : inline bool
     382    247448285 : hash_map_safe_put (hash_map<K,V,H> *&h, const K& k, const V& v,
     383              :                    size_t size = default_hash_map_size)
     384              : {
     385    247448285 :   return hash_map_maybe_create<ggc> (h, size)->put (k, v);
     386              : }
     387              : 
     388              : #endif
        

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.