1/* String pool for GCC. 2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 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 2, 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 COPYING. If not, write to the Free 19Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 2002110-1301, USA. */ 21 22/* String text, identifier text and identifier node allocator. Strings 23 allocated by ggc_alloc_string are stored in an obstack which is 24 never shrunk. Identifiers are uniquely stored in a hash table. 25 26 We use cpplib's hash table implementation. libiberty's 27 hashtab.c is not used because it requires 100% average space 28 overhead per string, which is unacceptable. Also, this algorithm 29 is faster. */ 30 31#include "config.h" 32#include "system.h" 33#include "coretypes.h" 34#include "tm.h" 35#include "ggc.h" 36#include "tree.h" 37#include "symtab.h" 38#include "cpplib.h" 39 40/* The "" allocated string. */ 41const char empty_string[] = ""; 42 43/* Character strings, each containing a single decimal digit. 44 Written this way to save space. */ 45const char digit_vector[] = { 46 '0', 0, '1', 0, '2', 0, '3', 0, '4', 0, 47 '5', 0, '6', 0, '7', 0, '8', 0, '9', 0 48}; 49 50struct ht *ident_hash; 51static struct obstack string_stack; 52 53static hashnode alloc_node (hash_table *); 54static int mark_ident (struct cpp_reader *, hashnode, const void *); 55 56static void * 57stringpool_ggc_alloc (size_t x) 58{ 59 return ggc_alloc (x); 60} 61 62/* Initialize the string pool. */ 63void 64init_stringpool (void) 65{ 66 /* Create with 16K (2^14) entries. */ 67 ident_hash = ht_create (14); 68 ident_hash->alloc_node = alloc_node; 69 ident_hash->alloc_subobject = stringpool_ggc_alloc; 70 gcc_obstack_init (&string_stack); 71} 72 73/* Allocate a hash node. */ 74static hashnode 75alloc_node (hash_table *table ATTRIBUTE_UNUSED) 76{ 77 return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE)); 78} 79 80/* Allocate and return a string constant of length LENGTH, containing 81 CONTENTS. If LENGTH is -1, CONTENTS is assumed to be a 82 nul-terminated string, and the length is calculated using strlen. 83 If the same string constant has been allocated before, that copy is 84 returned this time too. */ 85 86const char * 87ggc_alloc_string (const char *contents, int length) 88{ 89 if (length == -1) 90 length = strlen (contents); 91 92 if (length == 0) 93 return empty_string; 94 if (length == 1 && ISDIGIT (contents[0])) 95 return digit_string (contents[0] - '0'); 96 97 obstack_grow0 (&string_stack, contents, length); 98 return XOBFINISH (&string_stack, const char *); 99} 100 101/* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string). 102 If an identifier with that name has previously been referred to, 103 the same node is returned this time. */ 104 105#undef get_identifier 106 107tree 108get_identifier (const char *text) 109{ 110 hashnode ht_node = ht_lookup (ident_hash, 111 (const unsigned char *) text, 112 strlen (text), HT_ALLOC); 113 114 /* ht_node can't be NULL here. */ 115 return HT_IDENT_TO_GCC_IDENT (ht_node); 116} 117 118/* Identical to get_identifier, except that the length is assumed 119 known. */ 120 121tree 122get_identifier_with_length (const char *text, size_t length) 123{ 124 hashnode ht_node = ht_lookup (ident_hash, 125 (const unsigned char *) text, 126 length, HT_ALLOC); 127 128 /* ht_node can't be NULL here. */ 129 return HT_IDENT_TO_GCC_IDENT (ht_node); 130} 131 132/* If an identifier with the name TEXT (a null-terminated string) has 133 previously been referred to, return that node; otherwise return 134 NULL_TREE. */ 135 136tree 137maybe_get_identifier (const char *text) 138{ 139 hashnode ht_node; 140 141 ht_node = ht_lookup (ident_hash, (const unsigned char *) text, 142 strlen (text), HT_NO_INSERT); 143 if (ht_node) 144 return HT_IDENT_TO_GCC_IDENT (ht_node); 145 146 return NULL_TREE; 147} 148 149/* Report some basic statistics about the string pool. */ 150 151void 152stringpool_statistics (void) 153{ 154 ht_dump_statistics (ident_hash); 155} 156 157/* Mark an identifier for GC. */ 158 159static int 160mark_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h, 161 const void *v ATTRIBUTE_UNUSED) 162{ 163 gt_ggc_m_9tree_node (HT_IDENT_TO_GCC_IDENT (h)); 164 return 1; 165} 166 167/* Mark the trees hanging off the identifier node for GGC. These are 168 handled specially (not using gengtype) because of the special 169 treatment for strings. */ 170 171void 172ggc_mark_stringpool (void) 173{ 174 ht_forall (ident_hash, mark_ident, NULL); 175} 176 177/* Strings are _not_ GCed, but this routine exists so that a separate 178 roots table isn't needed for the few global variables that refer 179 to strings. */ 180 181void 182gt_ggc_m_S (void *x ATTRIBUTE_UNUSED) 183{ 184} 185 186/* Pointer-walking routine for strings (not very interesting, since 187 strings don't contain pointers). */ 188 189void 190gt_pch_p_S (void *obj ATTRIBUTE_UNUSED, void *x ATTRIBUTE_UNUSED, 191 gt_pointer_operator op ATTRIBUTE_UNUSED, 192 void *cookie ATTRIBUTE_UNUSED) 193{ 194} 195 196/* PCH pointer-walking routine for strings. */ 197 198void 199gt_pch_n_S (const void *x) 200{ 201 gt_pch_note_object ((void *)x, (void *)x, >_pch_p_S, 202 gt_types_enum_last); 203} 204 205/* Handle saving and restoring the string pool for PCH. */ 206 207/* SPD is saved in the PCH file and holds the information needed 208 to restore the string pool. */ 209 210struct string_pool_data GTY(()) 211{ 212 struct ht_identifier * * 213 GTY((length ("%h.nslots"), 214 nested_ptr (union tree_node, "%h ? GCC_IDENT_TO_HT_IDENT (%h) : NULL", 215 "%h ? HT_IDENT_TO_GCC_IDENT (%h) : NULL"))) 216 entries; 217 unsigned int nslots; 218 unsigned int nelements; 219}; 220 221static GTY(()) struct string_pool_data * spd; 222 223/* Save the stringpool data in SPD. */ 224 225void 226gt_pch_save_stringpool (void) 227{ 228 spd = ggc_alloc (sizeof (*spd)); 229 spd->nslots = ident_hash->nslots; 230 spd->nelements = ident_hash->nelements; 231 spd->entries = ggc_alloc (sizeof (spd->entries[0]) * spd->nslots); 232 memcpy (spd->entries, ident_hash->entries, 233 spd->nslots * sizeof (spd->entries[0])); 234} 235 236/* Return the stringpool to its state before gt_pch_save_stringpool 237 was called. */ 238 239void 240gt_pch_fixup_stringpool (void) 241{ 242} 243 244/* A PCH file has been restored, which loaded SPD; fill the real hash table 245 from SPD. */ 246 247void 248gt_pch_restore_stringpool (void) 249{ 250 ht_load (ident_hash, spd->entries, spd->nslots, spd->nelements, false); 251 spd = NULL; 252} 253 254#include "gt-stringpool.h" 255