* stringpool.c: Add comments to PCH saving/restoring routines.
[official-gcc.git] / gcc / stringpool.c
blob781518b9f7d4b549942213aa8b71605f90fb469b
1 /* String pool for GCC.
2 Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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. */
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.
25 We use cpplib's 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. */
30 #include "config.h"
31 #include "system.h"
32 #include "coretypes.h"
33 #include "tm.h"
34 #include "ggc.h"
35 #include "tree.h"
36 #include "symtab.h"
37 #include "cpplib.h"
39 /* The "" allocated string. */
40 const char empty_string[] = "";
42 /* Character strings, each containing a single decimal digit.
43 Written this way to save space. */
44 const char digit_vector[] = {
45 '0', 0, '1', 0, '2', 0, '3', 0, '4', 0,
46 '5', 0, '6', 0, '7', 0, '8', 0, '9', 0
49 struct ht *ident_hash;
50 static struct obstack string_stack;
52 static hashnode alloc_node (hash_table *);
53 static int mark_ident (struct cpp_reader *, hashnode, const void *);
54 static int ht_copy_and_clear (struct cpp_reader *, hashnode, const void *);
56 /* Initialize the string pool. */
57 void
58 init_stringpool (void)
60 /* Create with 16K (2^14) entries. */
61 ident_hash = ht_create (14);
62 ident_hash->alloc_node = alloc_node;
63 gcc_obstack_init (&string_stack);
66 /* Allocate a hash node. */
67 static hashnode
68 alloc_node (hash_table *table ATTRIBUTE_UNUSED)
70 return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE));
73 /* Allocate and return a string constant of length LENGTH, containing
74 CONTENTS. If LENGTH is -1, CONTENTS is assumed to be a
75 nul-terminated string, and the length is calculated using strlen.
76 If the same string constant has been allocated before, that copy is
77 returned this time too. */
79 const char *
80 ggc_alloc_string (const char *contents, int length)
82 if (length == -1)
83 length = strlen (contents);
85 if (length == 0)
86 return empty_string;
87 if (length == 1 && ISDIGIT (contents[0]))
88 return digit_string (contents[0] - '0');
90 obstack_grow0 (&string_stack, contents, length);
91 return obstack_finish (&string_stack);
94 /* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string).
95 If an identifier with that name has previously been referred to,
96 the same node is returned this time. */
98 #undef get_identifier
100 tree
101 get_identifier (const char *text)
103 hashnode ht_node = ht_lookup (ident_hash,
104 (const unsigned char *) text,
105 strlen (text), HT_ALLOC);
107 /* ht_node can't be NULL here. */
108 return HT_IDENT_TO_GCC_IDENT (ht_node);
111 /* Identical to get_identifier, except that the length is assumed
112 known. */
114 tree
115 get_identifier_with_length (const char *text, size_t length)
117 hashnode ht_node = ht_lookup (ident_hash,
118 (const unsigned char *) text,
119 length, HT_ALLOC);
121 /* ht_node can't be NULL here. */
122 return HT_IDENT_TO_GCC_IDENT (ht_node);
125 /* If an identifier with the name TEXT (a null-terminated string) has
126 previously been referred to, return that node; otherwise return
127 NULL_TREE. */
129 tree
130 maybe_get_identifier (const char *text)
132 hashnode ht_node;
134 ht_node = ht_lookup (ident_hash, (const unsigned char *) text,
135 strlen (text), HT_NO_INSERT);
136 if (ht_node)
137 return HT_IDENT_TO_GCC_IDENT (ht_node);
139 return NULL_TREE;
142 /* Report some basic statistics about the string pool. */
144 void
145 stringpool_statistics (void)
147 ht_dump_statistics (ident_hash);
150 /* Mark an identifier for GC. */
152 static int
153 mark_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h,
154 const void *v ATTRIBUTE_UNUSED)
156 gt_ggc_m_9tree_node (HT_IDENT_TO_GCC_IDENT (h));
157 return 1;
160 /* Mark the trees hanging off the identifier node for GGC. These are
161 handled specially (not using gengtype) because of the special
162 treatment for strings. */
164 void
165 ggc_mark_stringpool (void)
167 ht_forall (ident_hash, mark_ident, NULL);
170 /* Strings are _not_ GCed, but this routine exists so that a separate
171 roots table isn't needed for the few global variables that refer
172 to strings. */
174 void
175 gt_ggc_m_S (void *x ATTRIBUTE_UNUSED)
179 /* Pointer-walking routine for strings (not very interesting, since
180 strings don't contain pointers). */
182 void
183 gt_pch_p_S (void *obj ATTRIBUTE_UNUSED, void *x ATTRIBUTE_UNUSED,
184 gt_pointer_operator op ATTRIBUTE_UNUSED,
185 void *cookie ATTRIBUTE_UNUSED)
189 /* PCH pointer-walking routine for strings. */
191 void
192 gt_pch_n_S (const void *x)
194 gt_pch_note_object ((void *)x, (void *)x, &gt_pch_p_S);
197 /* Handle saving and restoring the string pool for PCH. */
199 /* SPD is saved in the PCH file and holds the information needed
200 to restore the string pool. */
202 struct string_pool_data GTY(())
204 tree * GTY((length ("%h.nslots"))) entries;
205 unsigned int nslots;
206 unsigned int nelements;
209 static GTY(()) struct string_pool_data * spd;
211 /* Copy HP into the corresponding entry in HT2, and then clear
212 the cpplib parts of HP. */
214 static int
215 ht_copy_and_clear (cpp_reader *r ATTRIBUTE_UNUSED, hashnode hp, const void *ht2_p)
217 cpp_hashnode *h = CPP_HASHNODE (hp);
218 struct ht *ht2 = (struct ht *) ht2_p;
220 if (h->type != NT_VOID
221 && (h->flags & NODE_BUILTIN) == 0)
223 cpp_hashnode *h2 = CPP_HASHNODE (ht_lookup (ht2,
224 NODE_NAME (h),
225 NODE_LEN (h),
226 HT_ALLOC));
227 h2->type = h->type;
228 memcpy (&h2->value, &h->value, sizeof (h->value));
230 h->type = NT_VOID;
231 memset (&h->value, 0, sizeof (h->value));
233 return 1;
236 /* The hash table as it was before gt_pch_save_stringpool was called. */
238 static struct ht *saved_ident_hash;
240 /* The hash table contains pointers to the cpp_hashnode inside the
241 lang_identifier. The PCH machinery can't handle pointers that refer
242 to the inside of an object, so to save the hash table for PCH the
243 pointers are adjusted and stored in the variable SPD. */
245 void
246 gt_pch_save_stringpool (void)
248 unsigned int i;
250 spd = ggc_alloc (sizeof (*spd));
251 spd->nslots = ident_hash->nslots;
252 spd->nelements = ident_hash->nelements;
253 spd->entries = ggc_alloc (sizeof (tree *) * spd->nslots);
254 for (i = 0; i < spd->nslots; i++)
255 if (ident_hash->entries[i] != NULL)
256 spd->entries[i] = HT_IDENT_TO_GCC_IDENT (ident_hash->entries[i]);
257 else
258 spd->entries[i] = NULL;
260 saved_ident_hash = ht_create (14);
261 saved_ident_hash->alloc_node = alloc_node;
262 ht_forall (ident_hash, ht_copy_and_clear, saved_ident_hash);
265 /* Return the stringpool to its state before gt_pch_save_stringpool
266 was called. */
268 void
269 gt_pch_fixup_stringpool (void)
271 ht_forall (saved_ident_hash, ht_copy_and_clear, ident_hash);
272 ht_destroy (saved_ident_hash);
273 saved_ident_hash = 0;
276 /* A PCH file has been restored, which loaded SPD; fill the real hash table
277 with adjusted pointers from SPD. */
279 void
280 gt_pch_restore_stringpool (void)
282 unsigned int i;
284 ident_hash->nslots = spd->nslots;
285 ident_hash->nelements = spd->nelements;
286 ident_hash->entries = xrealloc (ident_hash->entries,
287 sizeof (hashnode) * spd->nslots);
288 for (i = 0; i < spd->nslots; i++)
289 if (spd->entries[i] != NULL)
290 ident_hash->entries[i] = GCC_IDENT_TO_HT_IDENT (spd->entries[i]);
291 else
292 ident_hash->entries[i] = NULL;
294 spd = NULL;
297 #include "gt-stringpool.h"