1 /* String pool for GCC. 2 Copyright (C) 2000, 2001 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 2, 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 COPYING. If not, write to the Free 18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 19 02111-1307, USA. */ 20 21 /* String text, identifier text and identifier node allocator. Strings 22 allocated by ggc_alloc_string are stored in an obstack which is 23 never shrunk. Identifiers are uniquely stored in a hash table. 24 25 We have our own private hash table implementation. libiberty's 26 hashtab.c is not used because it requires 100% average space 27 overhead per string, which is unacceptable. Also, this algorithm 28 is faster. */ 29 30 #include "config.h" 31 #include "system.h" 32 #include "ggc.h" 33 #include "tree.h" 34 #include "hashtable.h" 35 36 /* The "" allocated string. */ 37 const char empty_string[] = ""; 38 39 /* Character strings, each containing a single decimal digit. 40 Written this way to save space. */ 41 const char digit_vector[] = { 42 '0', 0, '1', 0, '2', 0, '3', 0, '4', 0, 43 '5', 0, '6', 0, '7', 0, '8', 0, '9', 0 44 }; 45 46 struct ht *ident_hash; 47 static struct obstack string_stack; 48 49 static hashnode alloc_node PARAMS ((hash_table *)); 50 static int mark_ident PARAMS ((struct cpp_reader *, hashnode, const PTR)); 51 static void mark_ident_hash PARAMS ((void *)); 52 53 /* Initialize the string pool. */ 54 void 55 init_stringpool () 56 { 57 /* Create with 16K (2^14) entries. */ 58 ident_hash = ht_create (14); 59 ident_hash->alloc_node = alloc_node; 60 gcc_obstack_init (&string_stack); 61 ggc_add_root (&ident_hash, 1, sizeof ident_hash, mark_ident_hash); 62 } 63 64 /* Allocate a hash node. */ 65 static hashnode 66 alloc_node (table) 67 hash_table *table ATTRIBUTE_UNUSED; 68 { 69 return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE)); 70 } 71 72 /* Allocate and return a string constant of length LENGTH, containing 73 CONTENTS. If LENGTH is -1, CONTENTS is assumed to be a 74 nul-terminated string, and the length is calculated using strlen. 75 If the same string constant has been allocated before, that copy is 76 returned this time too. */ 77 78 const char * 79 ggc_alloc_string (contents, length) 80 const char *contents; 81 int length; 82 { 83 if (length == -1) 84 length = strlen (contents); 85 86 if (length == 0) 87 return empty_string; 88 if (length == 1 && ISDIGIT (contents[0])) 89 return digit_string (contents[0] - '0'); 90 91 obstack_grow0 (&string_stack, contents, length); 92 return obstack_finish (&string_stack); 93 } 94 95 /* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string). 96 If an identifier with that name has previously been referred to, 97 the same node is returned this time. */ 98 99 tree 100 get_identifier (text) 101 const char *text; 102 { 103 hashnode ht_node = ht_lookup (ident_hash, 104 (const unsigned char *) text, 105 strlen (text), HT_ALLOC); 106 107 /* ht_node can't be NULL here. */ 108 return HT_IDENT_TO_GCC_IDENT (ht_node); 109 } 110 111 /* Identical to get_identifier, except that the length is assumed 112 known. */ 113 114 tree 115 get_identifier_with_length (text, length) 116 const char *text; 117 unsigned int length; 118 { 119 hashnode ht_node = ht_lookup (ident_hash, 120 (const unsigned char *) text, 121 length, HT_ALLOC); 122 123 /* ht_node can't be NULL here. */ 124 return HT_IDENT_TO_GCC_IDENT (ht_node); 125 } 126 127 /* If an identifier with the name TEXT (a null-terminated string) has 128 previously been referred to, return that node; otherwise return 129 NULL_TREE. */ 130 131 tree 132 maybe_get_identifier (text) 133 const char *text; 134 { 135 hashnode ht_node; 136 137 ht_node = ht_lookup (ident_hash, (const unsigned char *) text, 138 strlen (text), HT_NO_INSERT); 139 if (ht_node) 140 return HT_IDENT_TO_GCC_IDENT (ht_node); 141 142 return NULL_TREE; 143 } 144 145 /* Report some basic statistics about the string pool. */ 146 147 void 148 stringpool_statistics () 149 { 150 ht_dump_statistics (ident_hash); 151 } 152 153 /* Mark an identifier for GC. */ 154 155 static int 156 mark_ident (pfile, h, v) 157 struct cpp_reader *pfile ATTRIBUTE_UNUSED; 158 hashnode h; 159 const PTR v ATTRIBUTE_UNUSED; 160 { 161 ggc_mark_tree (HT_IDENT_TO_GCC_IDENT (h)); 162 return 1; 163 } 164 165 /* Mark all identifiers for GC. */ 166 167 static void 168 mark_ident_hash (arg) 169 PTR arg ATTRIBUTE_UNUSED; 170 { 171 ht_forall (ident_hash, mark_ident, NULL); 172 } 173