1 /* String pool for GCC.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004 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
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
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
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
32 #include "coretypes.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. */
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. */
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. */
80 ggc_alloc_string (const char *contents, int length)
83 length = strlen (contents);
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. */
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
115 get_identifier_with_length (const char *text, size_t length)
117 hashnode ht_node = ht_lookup (ident_hash,
118 (const unsigned char *) text,
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
130 maybe_get_identifier (const char *text)
134 ht_node = ht_lookup (ident_hash, (const unsigned char *) text,
135 strlen (text), HT_NO_INSERT);
137 return HT_IDENT_TO_GCC_IDENT (ht_node);
142 /* Report some basic statistics about the string pool. */
145 stringpool_statistics (void)
147 ht_dump_statistics (ident_hash);
150 /* Mark an identifier for GC. */
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));
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. */
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
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). */
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. */
192 gt_pch_n_S (const void *x)
194 gt_pch_note_object ((void *)x, (void *)x, >_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 struct ht_identifier * *
205 GTY((length ("%h.nslots"),
206 nested_ptr (union tree_node, "%h ? GCC_IDENT_TO_HT_IDENT (%h) : NULL",
207 "%h ? HT_IDENT_TO_GCC_IDENT (%h) : NULL")))
210 unsigned int nelements;
213 static GTY(()) struct string_pool_data * spd;
215 /* Copy HP into the corresponding entry in HT2, and then clear
216 the cpplib parts of HP. */
219 ht_copy_and_clear (cpp_reader *r ATTRIBUTE_UNUSED, hashnode hp, const void *ht2_p)
221 cpp_hashnode *h = CPP_HASHNODE (hp);
222 struct ht *ht2 = (struct ht *) ht2_p;
224 if (h->type != NT_VOID
225 && (h->flags & NODE_BUILTIN) == 0)
227 cpp_hashnode *h2 = CPP_HASHNODE (ht_lookup (ht2,
232 memcpy (&h2->value, &h->value, sizeof (h->value));
235 memset (&h->value, 0, sizeof (h->value));
240 /* The hash table as it was before gt_pch_save_stringpool was called. */
242 static struct ht *saved_ident_hash;
244 /* Prepare the stringpool to be written (by clearing all the cpp parts
245 of each entry) and place the data to be saved in SPD. Save the
246 current state in SAVED_IDENT_HASH so that gt_pch_fixup_stringpool
250 gt_pch_save_stringpool (void)
252 spd = ggc_alloc (sizeof (*spd));
253 spd->nslots = ident_hash->nslots;
254 spd->nelements = ident_hash->nelements;
255 spd->entries = ggc_alloc (sizeof (spd->entries[0]) * spd->nslots);
256 memcpy (spd->entries, ident_hash->entries,
257 spd->nslots * sizeof (spd->entries[0]));
259 saved_ident_hash = ht_create (14);
260 saved_ident_hash->alloc_node = alloc_node;
261 ht_forall (ident_hash, ht_copy_and_clear, saved_ident_hash);
264 /* Return the stringpool to its state before gt_pch_save_stringpool
268 gt_pch_fixup_stringpool (void)
270 ht_forall (saved_ident_hash, ht_copy_and_clear, ident_hash);
271 ht_destroy (saved_ident_hash);
272 saved_ident_hash = 0;
275 /* A PCH file has been restored, which loaded SPD; fill the real hash table
279 gt_pch_restore_stringpool (void)
281 ht_load (ident_hash, spd->entries, spd->nslots, spd->nelements, false);
285 #include "gt-stringpool.h"