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: 2024-12-21 13:15:12 Functions: 69.6 % 23 16
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* String pool for GCC.
       2                 :             :    Copyright (C) 2000-2024 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                 :  1776064574 : stringpool_ggc_alloc (size_t x)
      42                 :             : {
      43                 :  1776064574 :   return ggc_alloc_atomic (x);
      44                 :             : }
      45                 :             : 
      46                 :             : /* Initialize the string pool.  */
      47                 :             : void
      48                 :      280114 : 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                 :      280114 :   if (ident_hash)
      53                 :        1121 :     ht_destroy (ident_hash);
      54                 :      280114 :   if (ident_hash_extra)
      55                 :        1121 :     ht_destroy (ident_hash_extra);
      56                 :             : 
      57                 :             :   /* Create with 16K (2^14) entries.  */
      58                 :      280114 :   ident_hash = ht_create (14);
      59                 :      280114 :   ident_hash->alloc_node = alloc_node;
      60                 :      280114 :   ident_hash->alloc_subobject = stringpool_ggc_alloc;
      61                 :             : 
      62                 :             :   /* Create with 64 (2^6) entries.  */
      63                 :      280114 :   ident_hash_extra = ht_create (6);
      64                 :      280114 :   ident_hash_extra->alloc_node = [] (cpp_hash_table *)
      65                 :             :   {
      66                 :             :     return HT_NODE (ggc_cleared_alloc<cpp_hashnode_extra> ());
      67                 :             :   };
      68                 :      280114 :   ident_hash_extra->alloc_subobject = stringpool_ggc_alloc;
      69                 :      280114 : }
      70                 :             : 
      71                 :             : /* Allocate a hash node.  */
      72                 :             : static hashnode
      73                 :  1569520090 : alloc_node (cpp_hash_table *table ATTRIBUTE_UNUSED)
      74                 :             : {
      75                 :  1569520090 :   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                 :   368316226 : ggc_alloc_string (const char *contents, int length MEM_STAT_DECL)
      84                 :             : {
      85                 :   368316226 :   if (length == -1)
      86                 :   368177546 :     length = strlen (contents);
      87                 :             : 
      88                 :   368316226 :   if (!length)
      89                 :             :     return "";
      90                 :             : 
      91                 :   368119575 :   char *result = (char *) ggc_alloc_atomic (length + 1);
      92                 :   368119575 :   memcpy (result, contents, length);
      93                 :   368119575 :   result[length] = '\0';
      94                 :             : 
      95                 :   368119575 :   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                 :  1450865731 : get_identifier (const char *text)
     106                 :             : {
     107                 :  1450865731 :   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                 :  1450865731 :   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                 :   317199100 : get_identifier_with_length (const char *text, size_t length)
     120                 :             : {
     121                 :   317199100 :   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                 :   317199100 :   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                 :   343416989 : maybe_get_identifier (const char *text)
     135                 :             : {
     136                 :   343416989 :   hashnode ht_node;
     137                 :             : 
     138                 :   343416989 :   ht_node = ht_lookup (ident_hash, (const unsigned char *) text,
     139                 :             :                        strlen (text), HT_NO_INSERT);
     140                 :   343416989 :   if (ht_node)
     141                 :    33745194 :     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                 :  2208801521 : mark_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h,
     158                 :             :             const void *v ATTRIBUTE_UNUSED)
     159                 :             : {
     160                 :  2208801521 :   gt_ggc_m_9tree_node (HT_IDENT_TO_GCC_IDENT (h));
     161                 :  2208801521 :   return 1;
     162                 :             : }
     163                 :             : 
     164                 :             : /* Return true if an identifier should be removed from the table.  */
     165                 :             : 
     166                 :             : static int
     167                 :  2354715825 : maybe_delete_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h,
     168                 :             :                     const void *v ATTRIBUTE_UNUSED)
     169                 :             : {
     170                 :  2354715825 :   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                 :      148682 : ggc_mark_stringpool (void)
     179                 :             : {
     180                 :      148682 :   ht_forall (ident_hash, mark_ident, NULL);
     181                 :      148682 :   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                 :      148682 : }
     188                 :             : 
     189                 :             : /* Purge the identifier hash of identifiers which are no longer
     190                 :             :    referenced.  */
     191                 :             : 
     192                 :             : void
     193                 :      541707 : ggc_purge_stringpool (void)
     194                 :             : {
     195                 :      541707 :   ht_purge (ident_hash, maybe_delete_ident, NULL);
     196                 :      541707 :   ht_purge (ident_hash_extra,
     197                 :             :             [] (cpp_reader *, hashnode h, const void *) -> int
     198                 :             :             {
     199                 :             :               return !ggc_marked_p (h);
     200                 :             :             }, nullptr);
     201                 :      541707 : }
     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                 :      594562 : gt_pch_n_S (const void *x)
     218                 :             : {
     219                 :      594562 :   gt_pch_note_object (CONST_CAST (void *, x), CONST_CAST (void *, x),
     220                 :             :                       &gt_pch_p_S);
     221                 :      594562 : }
     222                 :             : 
     223                 :             : void
     224                 :     2139955 : gt_pch_n_S2 (const void *x, size_t string_len)
     225                 :             : {
     226                 :     2139955 :   gt_pch_note_object (CONST_CAST (void *, x), CONST_CAST (void *, x),
     227                 :             :                       &gt_pch_p_S, string_len);
     228                 :     2139955 : }
     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                 :         478 : gt_pch_save_stringpool (void)
     295                 :             : {
     296                 :         478 :   spd = ggc_alloc<string_pool_data> ();
     297                 :         478 :   spd->nslots = ident_hash->nslots;
     298                 :         478 :   spd->nelements = ident_hash->nelements;
     299                 :         478 :   spd->entries = ggc_vec_alloc<ht_identifier_ptr> (spd->nslots);
     300                 :         478 :   memcpy (spd->entries, ident_hash->entries,
     301                 :         478 :           spd->nslots * sizeof (spd->entries[0]));
     302                 :             : 
     303                 :         478 :   spd2 = ggc_alloc<string_pool_data_extra> ();
     304                 :         478 :   spd2->nslots = ident_hash_extra->nslots;
     305                 :         478 :   spd2->nelements = ident_hash_extra->nelements;
     306                 :         478 :   spd2->entries = ggc_vec_alloc<ht_identifier_ptr> (spd2->nslots);
     307                 :         478 :   memcpy (spd2->entries, ident_hash_extra->entries,
     308                 :         478 :           spd2->nslots * sizeof (spd2->entries[0]));
     309                 :         478 : }
     310                 :             : 
     311                 :             : /* Return the stringpool to its state before gt_pch_save_stringpool
     312                 :             :    was called.  */
     313                 :             : 
     314                 :             : void
     315                 :         478 : gt_pch_fixup_stringpool (void)
     316                 :             : {
     317                 :         478 : }
     318                 :             : 
     319                 :             : /* A PCH file has been restored, which loaded SPD; fill the real hash table
     320                 :             :    from SPD.  */
     321                 :             : 
     322                 :             : void
     323                 :         347 : gt_pch_restore_stringpool (void)
     324                 :             : {
     325                 :         347 :   ht_load (ident_hash, spd->entries, spd->nslots, spd->nelements, false);
     326                 :         347 :   ht_load (ident_hash_extra, spd2->entries, spd2->nslots, spd2->nelements,
     327                 :             :            false);
     328                 :         347 :   spd = NULL;
     329                 :         347 :   spd2 = NULL;
     330                 :         347 : }
     331                 :             : 
     332                 :             : #include "gt-stringpool.h"
        

Generated by: LCOV version 2.1-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.