LCOV - code coverage report
Current view: top level - gcc - stringpool.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 80.0 % 95 76
Test Date: 2026-02-28 14:20:25 Functions: 69.6 % 23 16
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* String pool for GCC.
       2              :    Copyright (C) 2000-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              : /* String text, identifier text and identifier node allocator.
      21              :    Identifiers are uniquely stored in a hash table.
      22              : 
      23              :    We use cpplib's hash table implementation.  libiberty's
      24              :    hashtab.c is not used because it requires 100% average space
      25              :    overhead per string, which is unacceptable.  Also, this algorithm
      26              :    is faster.  */
      27              : 
      28              : #include "config.h"
      29              : #include "system.h"
      30              : #include "coretypes.h"
      31              : #include "tree.h"
      32              : #include "cpplib.h"
      33              : 
      34              : struct ht *ident_hash;
      35              : struct ht *ident_hash_extra;
      36              : 
      37              : static hashnode alloc_node (cpp_hash_table *);
      38              : static int mark_ident (struct cpp_reader *, hashnode, const void *);
      39              : 
      40              : static void *
      41   1920536570 : stringpool_ggc_alloc (size_t x)
      42              : {
      43   1920536570 :   return ggc_alloc_atomic (x);
      44              : }
      45              : 
      46              : /* Initialize the string pool.  */
      47              : void
      48       285722 : init_stringpool (void)
      49              : {
      50              :   /* Clean up if we're called more than once.
      51              :      (We can't make this idempotent since identifiers contain state) */
      52       285722 :   if (ident_hash)
      53         1200 :     ht_destroy (ident_hash);
      54       285722 :   if (ident_hash_extra)
      55         1200 :     ht_destroy (ident_hash_extra);
      56              : 
      57              :   /* Create with 16K (2^14) entries.  */
      58       285722 :   ident_hash = ht_create (14);
      59       285722 :   ident_hash->alloc_node = alloc_node;
      60       285722 :   ident_hash->alloc_subobject = stringpool_ggc_alloc;
      61              : 
      62              :   /* Create with 64 (2^6) entries.  */
      63       285722 :   ident_hash_extra = ht_create (6);
      64       285722 :   ident_hash_extra->alloc_node = [] (cpp_hash_table *)
      65              :   {
      66              :     return HT_NODE (ggc_cleared_alloc<cpp_hashnode_extra> ());
      67              :   };
      68       285722 :   ident_hash_extra->alloc_subobject = stringpool_ggc_alloc;
      69       285722 : }
      70              : 
      71              : /* Allocate a hash node.  */
      72              : static hashnode
      73   1693858740 : alloc_node (cpp_hash_table *table ATTRIBUTE_UNUSED)
      74              : {
      75   1693858740 :   return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE));
      76              : }
      77              : 
      78              : /* Allocate and return a string constant of length LENGTH, containing
      79              :    CONTENTS.  If LENGTH is -1, CONTENTS is assumed to be a
      80              :    nul-terminated string, and the length is calculated using strlen.  */
      81              : 
      82              : const char *
      83    513711821 : ggc_alloc_string (const char *contents, int length MEM_STAT_DECL)
      84              : {
      85    513711821 :   if (length == -1)
      86    513569604 :     length = strlen (contents);
      87              : 
      88    513711821 :   if (!length)
      89              :     return "";
      90              : 
      91    513511464 :   char *result = (char *) ggc_alloc_atomic (length + 1);
      92    513511464 :   memcpy (result, contents, length);
      93    513511464 :   result[length] = '\0';
      94              : 
      95    513511464 :   return (const char *) result;
      96              : }
      97              : 
      98              : /* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string).
      99              :    If an identifier with that name has previously been referred to,
     100              :    the same node is returned this time.  */
     101              : 
     102              : #undef get_identifier
     103              : 
     104              : tree
     105   1662888430 : get_identifier (const char *text)
     106              : {
     107   1662888430 :   hashnode ht_node = ht_lookup (ident_hash,
     108              :                                 (const unsigned char *) text,
     109              :                                 strlen (text), HT_ALLOC);
     110              : 
     111              :   /* ht_node can't be NULL here.  */
     112   1662888430 :   return HT_IDENT_TO_GCC_IDENT (ht_node);
     113              : }
     114              : 
     115              : /* Identical to get_identifier, except that the length is assumed
     116              :    known.  */
     117              : 
     118              : tree
     119    335004144 : get_identifier_with_length (const char *text, size_t length)
     120              : {
     121    335004144 :   hashnode ht_node = ht_lookup (ident_hash,
     122              :                                 (const unsigned char *) text,
     123              :                                 length, HT_ALLOC);
     124              : 
     125              :   /* ht_node can't be NULL here.  */
     126    335004144 :   return HT_IDENT_TO_GCC_IDENT (ht_node);
     127              : }
     128              : 
     129              : /* If an identifier with the name TEXT (a null-terminated string) has
     130              :    previously been referred to, return that node; otherwise return
     131              :    NULL_TREE.  */
     132              : 
     133              : tree
     134    394152109 : maybe_get_identifier (const char *text)
     135              : {
     136    394152109 :   hashnode ht_node;
     137              : 
     138    394152109 :   ht_node = ht_lookup (ident_hash, (const unsigned char *) text,
     139              :                        strlen (text), HT_NO_INSERT);
     140    394152109 :   if (ht_node)
     141     34782327 :     return HT_IDENT_TO_GCC_IDENT (ht_node);
     142              : 
     143              :   return NULL_TREE;
     144              : }
     145              : 
     146              : /* Report some basic statistics about the string pool.  */
     147              : 
     148              : void
     149            0 : stringpool_statistics (void)
     150              : {
     151            0 :   ht_dump_statistics (ident_hash);
     152            0 : }
     153              : 
     154              : /* Mark an identifier for GC.  */
     155              : 
     156              : static int
     157   2392688822 : mark_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h,
     158              :             const void *v ATTRIBUTE_UNUSED)
     159              : {
     160   2392688822 :   gt_ggc_m_9tree_node (HT_IDENT_TO_GCC_IDENT (h));
     161   2392688822 :   return 1;
     162              : }
     163              : 
     164              : /* Return true if an identifier should be removed from the table.  */
     165              : 
     166              : static int
     167   2430635047 : maybe_delete_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h,
     168              :                     const void *v ATTRIBUTE_UNUSED)
     169              : {
     170   2430635047 :   return !ggc_marked_p (HT_IDENT_TO_GCC_IDENT (h));
     171              : }
     172              : 
     173              : /* Mark the trees hanging off the identifier node for GGC.  These are
     174              :    handled specially (not using gengtype) because identifiers are only
     175              :    roots during one part of compilation.  */
     176              : 
     177              : void
     178       154392 : ggc_mark_stringpool (void)
     179              : {
     180       154392 :   ht_forall (ident_hash, mark_ident, NULL);
     181       154392 :   ht_forall (ident_hash_extra,
     182              :              [] (cpp_reader *, hashnode h, const void *)
     183              :              {
     184              :                gt_ggc_m_18cpp_hashnode_extra (h);
     185              :                return 1;
     186              :              }, nullptr);
     187       154392 : }
     188              : 
     189              : /* Purge the identifier hash of identifiers which are no longer
     190              :    referenced.  */
     191              : 
     192              : void
     193       564748 : ggc_purge_stringpool (void)
     194              : {
     195       564748 :   ht_purge (ident_hash, maybe_delete_ident, NULL);
     196       564748 :   ht_purge (ident_hash_extra,
     197              :             [] (cpp_reader *, hashnode h, const void *) -> int
     198              :             {
     199              :               return !ggc_marked_p (h);
     200              :             }, nullptr);
     201       564748 : }
     202              : 
     203              : /* Pointer-walking routine for strings (not very interesting, since
     204              :    strings don't contain pointers).  */
     205              : 
     206              : void
     207            0 : gt_pch_p_S (void *obj ATTRIBUTE_UNUSED, void *x ATTRIBUTE_UNUSED,
     208              :             gt_pointer_operator op ATTRIBUTE_UNUSED,
     209              :             void *cookie ATTRIBUTE_UNUSED)
     210              : {
     211            0 :   gcc_unreachable ();
     212              : }
     213              : 
     214              : /* PCH pointer-walking routine for strings.  */
     215              : 
     216              : void
     217       740237 : gt_pch_n_S (const void *x)
     218              : {
     219       740237 :   gt_pch_note_object (const_cast<void *> (x), const_cast<void *> (x),
     220              :                       &gt_pch_p_S);
     221       740237 : }
     222              : 
     223              : void
     224      2058330 : gt_pch_n_S2 (const void *x, size_t string_len)
     225              : {
     226      2058330 :   gt_pch_note_object (const_cast<void *> (x), const_cast<void *> (x),
     227              :                       &gt_pch_p_S, string_len);
     228      2058330 : }
     229              : 
     230              : 
     231              : /* User-callable entry point for marking string X.  */
     232              : 
     233              : void
     234            0 : gt_pch_nx (const char *& x)
     235              : {
     236            0 :   gt_pch_n_S (x);
     237            0 : }
     238              : 
     239              : void
     240            0 : gt_pch_nx (char *& x)
     241              : {
     242            0 :   gt_pch_n_S (x);
     243            0 : }
     244              : 
     245              : void
     246            0 : gt_pch_nx (unsigned char *& x)
     247              : {
     248            0 :   gt_pch_n_S (x);
     249            0 : }
     250              : 
     251              : void
     252            0 : gt_pch_nx (unsigned char& x ATTRIBUTE_UNUSED)
     253              : {
     254            0 : }
     255              : 
     256              : void
     257            0 : gt_pch_nx (unsigned char *x, gt_pointer_operator op, void *cookie)
     258              : {
     259            0 :   op (x, NULL, cookie);
     260            0 : }
     261              : 
     262              : /* Handle saving and restoring the string pool for PCH.  */
     263              : 
     264              : /* SPD is saved in the PCH file and holds the information needed
     265              :    to restore the string pool.  */
     266              : 
     267              : struct GTY(()) string_pool_data {
     268              :   ht_identifier_ptr *
     269              :     GTY((length ("%h.nslots"),
     270              :          nested_ptr (union tree_node, "%h ? GCC_IDENT_TO_HT_IDENT (%h) : NULL",
     271              :                      "%h ? HT_IDENT_TO_GCC_IDENT (%h) : NULL")))
     272              :     entries;
     273              :   unsigned int nslots;
     274              :   unsigned int nelements;
     275              : };
     276              : 
     277              : struct GTY (()) string_pool_data_extra
     278              : {
     279              :   ht_identifier_ptr *
     280              :     GTY((length ("%h.nslots"),
     281              :          nested_ptr (cpp_hashnode_extra, "%h ? HT_NODE (%h) : nullptr",
     282              :                      "(cpp_hashnode_extra *)%h")))
     283              :     entries;
     284              :   unsigned int nslots;
     285              :   unsigned int nelements;
     286              : };
     287              : 
     288              : static GTY(()) struct string_pool_data * spd;
     289              : static GTY(()) struct string_pool_data_extra *spd2;
     290              : 
     291              : /* Save the stringpool data in SPD.  */
     292              : 
     293              : void
     294          428 : gt_pch_save_stringpool (void)
     295              : {
     296          428 :   spd = ggc_alloc<string_pool_data> ();
     297          428 :   spd->nslots = ident_hash->nslots;
     298          428 :   spd->nelements = ident_hash->nelements;
     299          428 :   spd->entries = ggc_vec_alloc<ht_identifier_ptr> (spd->nslots);
     300          428 :   memcpy (spd->entries, ident_hash->entries,
     301          428 :           spd->nslots * sizeof (spd->entries[0]));
     302              : 
     303          428 :   spd2 = ggc_alloc<string_pool_data_extra> ();
     304          428 :   spd2->nslots = ident_hash_extra->nslots;
     305          428 :   spd2->nelements = ident_hash_extra->nelements;
     306          428 :   spd2->entries = ggc_vec_alloc<ht_identifier_ptr> (spd2->nslots);
     307          428 :   memcpy (spd2->entries, ident_hash_extra->entries,
     308          428 :           spd2->nslots * sizeof (spd2->entries[0]));
     309          428 : }
     310              : 
     311              : /* Return the stringpool to its state before gt_pch_save_stringpool
     312              :    was called.  */
     313              : 
     314              : void
     315          428 : gt_pch_fixup_stringpool (void)
     316              : {
     317          428 : }
     318              : 
     319              : /* A PCH file has been restored, which loaded SPD; fill the real hash table
     320              :    from SPD.  */
     321              : 
     322              : void
     323          350 : gt_pch_restore_stringpool (void)
     324              : {
     325          350 :   ht_load (ident_hash, spd->entries, spd->nslots, spd->nelements, false);
     326          350 :   ht_load (ident_hash_extra, spd2->entries, spd2->nslots, spd2->nelements,
     327              :            false);
     328          350 :   spd = NULL;
     329          350 :   spd2 = NULL;
     330          350 : }
     331              : 
     332              : #include "gt-stringpool.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.