1/* String pool for GCC. 2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 3 Free Software Foundation, Inc. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 3, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING3. If not see 19<http://www.gnu.org/licenses/>. */ 20 21/* String text, identifier text and identifier node allocator. 22 Identifiers are uniquely stored in a hash table. 23 24 We use cpplib's hash table implementation. libiberty's 25 hashtab.c is not used because it requires 100% average space 26 overhead per string, which is unacceptable. Also, this algorithm 27 is faster. */ 28 29#include "config.h" 30#include "system.h" 31#include "coretypes.h" 32#include "tm.h" 33#include "ggc.h" 34#include "tree.h" 35#include "symtab.h" 36#include "cpplib.h" 37 38/* The "" allocated string. */ 39const char empty_string[] = ""; 40 41/* Character strings, each containing a single decimal digit. 42 Written this way to save space. */ 43const char digit_vector[] = { 44 '0', 0, '1', 0, '2', 0, '3', 0, '4', 0, 45 '5', 0, '6', 0, '7', 0, '8', 0, '9', 0 46}; 47 48struct ht *ident_hash; 49 50static hashnode alloc_node (hash_table *); 51static int mark_ident (struct cpp_reader *, hashnode, const void *); 52 53static void * 54stringpool_ggc_alloc (size_t x) 55{ 56 return ggc_alloc (x); 57} 58 59/* Initialize the string pool. */ 60void 61init_stringpool (void) 62{ 63 /* Create with 16K (2^14) entries. */ 64 ident_hash = ht_create (14); 65 ident_hash->alloc_node = alloc_node; 66 ident_hash->alloc_subobject = stringpool_ggc_alloc; 67} 68 69/* Allocate a hash node. */ 70static hashnode 71alloc_node (hash_table *table ATTRIBUTE_UNUSED) 72{ 73 return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE)); 74} 75 76/* Allocate and return a string constant of length LENGTH, containing 77 CONTENTS. If LENGTH is -1, CONTENTS is assumed to be a 78 nul-terminated string, and the length is calculated using strlen. */ 79 80const char * 81ggc_alloc_string (const char *contents, int length) 82{ 83 char *result; 84 85 if (length == -1) 86 length = strlen (contents); 87 88 if (length == 0) 89 return empty_string; 90 if (length == 1 && ISDIGIT (contents[0])) 91 return digit_string (contents[0] - '0'); 92 93 result = GGC_NEWVAR (char, length + 1); 94 memcpy (result, contents, length); 95 result[length] = '\0'; 96 return (const char *) result; 97} 98 99/* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string). 100 If an identifier with that name has previously been referred to, 101 the same node is returned this time. */ 102 103#undef get_identifier 104 105tree 106get_identifier (const char *text) 107{ 108 hashnode ht_node = ht_lookup (ident_hash, 109 (const unsigned char *) text, 110 strlen (text), HT_ALLOC); 111 112 /* ht_node can't be NULL here. */ 113 return HT_IDENT_TO_GCC_IDENT (ht_node); 114} 115 116/* Identical to get_identifier, except that the length is assumed 117 known. */ 118 119tree 120get_identifier_with_length (const char *text, size_t length) 121{ 122 hashnode ht_node = ht_lookup (ident_hash, 123 (const unsigned char *) text, 124 length, HT_ALLOC); 125 126 /* ht_node can't be NULL here. */ 127 return HT_IDENT_TO_GCC_IDENT (ht_node); 128} 129 130/* If an identifier with the name TEXT (a null-terminated string) has 131 previously been referred to, return that node; otherwise return 132 NULL_TREE. */ 133 134tree 135maybe_get_identifier (const char *text) 136{ 137 hashnode ht_node; 138 139 ht_node = ht_lookup (ident_hash, (const unsigned char *) text, 140 strlen (text), HT_NO_INSERT); 141 if (ht_node) 142 return HT_IDENT_TO_GCC_IDENT (ht_node); 143 144 return NULL_TREE; 145} 146 147/* Report some basic statistics about the string pool. */ 148 149void 150stringpool_statistics (void) 151{ 152 ht_dump_statistics (ident_hash); 153} 154 155/* Mark an identifier for GC. */ 156 157static int 158mark_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h, 159 const void *v ATTRIBUTE_UNUSED) 160{ 161 gt_ggc_m_9tree_node (HT_IDENT_TO_GCC_IDENT (h)); 162 return 1; 163} 164 165/* Return true if an identifier should be removed from the table. */ 166 167static int 168maybe_delete_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h, 169 const void *v ATTRIBUTE_UNUSED) 170{ 171 return !ggc_marked_p (HT_IDENT_TO_GCC_IDENT (h)); 172} 173 174/* Mark the trees hanging off the identifier node for GGC. These are 175 handled specially (not using gengtype) because identifiers are only 176 roots during one part of compilation. */ 177 178void 179ggc_mark_stringpool (void) 180{ 181 ht_forall (ident_hash, mark_ident, NULL); 182} 183 184/* Purge the identifier hash of identifiers which are no longer 185 referenced. */ 186 187void 188ggc_purge_stringpool (void) 189{ 190 ht_purge (ident_hash, maybe_delete_ident, NULL); 191} 192 193/* Pointer-walking routine for strings (not very interesting, since 194 strings don't contain pointers). */ 195 196void 197gt_pch_p_S (void *obj ATTRIBUTE_UNUSED, void *x ATTRIBUTE_UNUSED, 198 gt_pointer_operator op ATTRIBUTE_UNUSED, 199 void *cookie ATTRIBUTE_UNUSED) 200{ 201} 202 203/* PCH pointer-walking routine for strings. */ 204 205void 206gt_pch_n_S (const void *x) 207{ 208 gt_pch_note_object (CONST_CAST (void *, x), CONST_CAST (void *, x), 209 >_pch_p_S, gt_types_enum_last); 210} 211 212/* Handle saving and restoring the string pool for PCH. */ 213 214/* SPD is saved in the PCH file and holds the information needed 215 to restore the string pool. */ 216 217struct GTY(()) string_pool_data { 218 struct ht_identifier * * 219 GTY((length ("%h.nslots"), 220 nested_ptr (union tree_node, "%h ? GCC_IDENT_TO_HT_IDENT (%h) : NULL", 221 "%h ? HT_IDENT_TO_GCC_IDENT (%h) : NULL"))) 222 entries; 223 unsigned int nslots; 224 unsigned int nelements; 225}; 226 227static GTY(()) struct string_pool_data * spd; 228 229/* Save the stringpool data in SPD. */ 230 231void 232gt_pch_save_stringpool (void) 233{ 234 spd = GGC_NEW (struct string_pool_data); 235 spd->nslots = ident_hash->nslots; 236 spd->nelements = ident_hash->nelements; 237 spd->entries = GGC_NEWVEC (struct ht_identifier *, spd->nslots); 238 memcpy (spd->entries, ident_hash->entries, 239 spd->nslots * sizeof (spd->entries[0])); 240} 241 242/* Return the stringpool to its state before gt_pch_save_stringpool 243 was called. */ 244 245void 246gt_pch_fixup_stringpool (void) 247{ 248} 249 250/* A PCH file has been restored, which loaded SPD; fill the real hash table 251 from SPD. */ 252 253void 254gt_pch_restore_stringpool (void) 255{ 256 ht_load (ident_hash, spd->entries, spd->nslots, spd->nelements, false); 257 spd = NULL; 258} 259 260#include "gt-stringpool.h" 261