stringpool.c revision 256281
111894Speter/* String pool for GCC. 211894Speter Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 311894Speter Free Software Foundation, Inc. 411894Speter 59SjkhThis file is part of GCC. 69Sjkh 79SjkhGCC is free software; you can redistribute it and/or modify it under 89Sjkhthe terms of the GNU General Public License as published by the Free 99SjkhSoftware Foundation; either version 2, or (at your option) any later 109Sjkhversion. 119Sjkh 129SjkhGCC is distributed in the hope that it will be useful, but WITHOUT ANY 139SjkhWARRANTY; without even the implied warranty of MERCHANTABILITY or 149SjkhFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 159Sjkhfor more details. 169Sjkh 179SjkhYou should have received a copy of the GNU General Public License 189Sjkhalong with GCC; see the file COPYING. If not, write to the Free 199SjkhSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 2011894Speter02110-1301, USA. */ 2111894Speter 2211894Speter/* String text, identifier text and identifier node allocator. Strings 239Sjkh allocated by ggc_alloc_string are stored in an obstack which is 249Sjkh never shrunk. Identifiers are uniquely stored in a hash table. 259Sjkh 269Sjkh We use cpplib's hash table implementation. libiberty's 279Sjkh hashtab.c is not used because it requires 100% average space 289Sjkh overhead per string, which is unacceptable. Also, this algorithm 299Sjkh is faster. */ 309Sjkh 3111894Speter#include "config.h" 3211894Speter#include "system.h" 338858Srgrimes#include "coretypes.h" 3411894Speter#include "tm.h" 3511894Speter#include "ggc.h" 3611894Speter#include "tree.h" 371494Srgrimes#include "symtab.h" 3811894Speter#include "cpplib.h" 3911894Speter 4011894Speter/* The "" allocated string. */ 4111894Speterconst char empty_string[] = ""; 4211894Speter 4311894Speter/* Character strings, each containing a single decimal digit. 4411894Speter Written this way to save space. */ 4511894Speterconst char digit_vector[] = { 4611894Speter '0', 0, '1', 0, '2', 0, '3', 0, '4', 0, 4711894Speter '5', 0, '6', 0, '7', 0, '8', 0, '9', 0 4811894Speter}; 4911894Speter 5011894Speterstruct ht *ident_hash; 5111894Speterstatic struct obstack string_stack; 5211894Speter 5311894Speterstatic hashnode alloc_node (hash_table *); 5411894Speterstatic int mark_ident (struct cpp_reader *, hashnode, const void *); 5511894Speter 5611894Speterstatic void * 5711894Speterstringpool_ggc_alloc (size_t x) 5811894Speter{ 5911894Speter return ggc_alloc (x); 6011894Speter} 6111894Speter 6211894Speter/* Initialize the string pool. */ 639Sjkhvoid 649Sjkhinit_stringpool (void) 659Sjkh{ 669Sjkh /* Create with 16K (2^14) entries. */ 679Sjkh ident_hash = ht_create (14); 689Sjkh ident_hash->alloc_node = alloc_node; 699Sjkh ident_hash->alloc_subobject = stringpool_ggc_alloc; 709Sjkh gcc_obstack_init (&string_stack); 719Sjkh} 729Sjkh 739Sjkh/* Allocate a hash node. */ 749Sjkhstatic hashnode 759Sjkhalloc_node (hash_table *table ATTRIBUTE_UNUSED) 769Sjkh{ 779Sjkh return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE)); 789Sjkh} 799Sjkh 809Sjkh/* Allocate and return a string constant of length LENGTH, containing 819Sjkh CONTENTS. If LENGTH is -1, CONTENTS is assumed to be a 829Sjkh nul-terminated string, and the length is calculated using strlen. 839Sjkh If the same string constant has been allocated before, that copy is 849Sjkh returned this time too. */ 859Sjkh 869Sjkhconst char * 879Sjkhggc_alloc_string (const char *contents, int length) 889Sjkh{ 899Sjkh if (length == -1) 909Sjkh length = strlen (contents); 919Sjkh 929Sjkh if (length == 0) 939Sjkh return empty_string; 949Sjkh if (length == 1 && ISDIGIT (contents[0])) 959Sjkh return digit_string (contents[0] - '0'); 969Sjkh 979Sjkh obstack_grow0 (&string_stack, contents, length); 989Sjkh return XOBFINISH (&string_stack, const char *); 998858Srgrimes} 1009Sjkh 1019Sjkh/* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string). 1029Sjkh If an identifier with that name has previously been referred to, 1038858Srgrimes the same node is returned this time. */ 1049Sjkh 1059Sjkh#undef get_identifier 1068858Srgrimes 1079Sjkhtree 1089Sjkhget_identifier (const char *text) 1099Sjkh{ 1108858Srgrimes hashnode ht_node = ht_lookup (ident_hash, 1119Sjkh (const unsigned char *) text, 1128858Srgrimes strlen (text), HT_ALLOC); 1139Sjkh 1148858Srgrimes /* ht_node can't be NULL here. */ 1159Sjkh return HT_IDENT_TO_GCC_IDENT (ht_node); 1169Sjkh} 1178858Srgrimes 1189Sjkh/* Identical to get_identifier, except that the length is assumed 1199Sjkh known. */ 1208858Srgrimes 1219Sjkhtree 1229Sjkhget_identifier_with_length (const char *text, size_t length) 1239Sjkh{ 1249Sjkh hashnode ht_node = ht_lookup (ident_hash, 1259Sjkh (const unsigned char *) text, 1269Sjkh length, HT_ALLOC); 1279Sjkh 1288858Srgrimes /* ht_node can't be NULL here. */ 1299Sjkh return HT_IDENT_TO_GCC_IDENT (ht_node); 1309Sjkh} 1319Sjkh 1329Sjkh/* If an identifier with the name TEXT (a null-terminated string) has 1339Sjkh previously been referred to, return that node; otherwise return 1349Sjkh NULL_TREE. */ 1359Sjkh 1369Sjkhtree 1379Sjkhmaybe_get_identifier (const char *text) 1389Sjkh{ 1399Sjkh hashnode ht_node; 1409Sjkh 1419Sjkh ht_node = ht_lookup (ident_hash, (const unsigned char *) text, 1429Sjkh strlen (text), HT_NO_INSERT); 1439Sjkh if (ht_node) 1449Sjkh return HT_IDENT_TO_GCC_IDENT (ht_node); 1459Sjkh 1469Sjkh return NULL_TREE; 1479Sjkh} 1489Sjkh 1499Sjkh/* Report some basic statistics about the string pool. */ 1509Sjkh 1519Sjkhvoid 1529Sjkhstringpool_statistics (void) 1539Sjkh{ 1549Sjkh ht_dump_statistics (ident_hash); 1559Sjkh} 1569Sjkh 1579Sjkh/* Mark an identifier for GC. */ 1589Sjkh 1599Sjkhstatic int 1609Sjkhmark_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h, 1619Sjkh const void *v ATTRIBUTE_UNUSED) 1629Sjkh{ 1639Sjkh gt_ggc_m_9tree_node (HT_IDENT_TO_GCC_IDENT (h)); 1649Sjkh return 1; 1659Sjkh} 1669Sjkh 1679Sjkh/* Mark the trees hanging off the identifier node for GGC. These are 1689Sjkh handled specially (not using gengtype) because of the special 1699Sjkh treatment for strings. */ 1709Sjkh 17111894Spetervoid 1729Sjkhggc_mark_stringpool (void) 1739Sjkh{ 17411894Speter ht_forall (ident_hash, mark_ident, NULL); 1759Sjkh} 1769Sjkh 1779Sjkh/* Strings are _not_ GCed, but this routine exists so that a separate 1789Sjkh roots table isn't needed for the few global variables that refer 1799Sjkh to strings. */ 1809Sjkh 18125699Spetervoid 18211894Spetergt_ggc_m_S (void *x ATTRIBUTE_UNUSED) 18311894Speter{ 1849Sjkh} 1859Sjkh 1869Sjkh/* Pointer-walking routine for strings (not very interesting, since 1879Sjkh strings don't contain pointers). */ 1889Sjkh 1899Sjkhvoid 1909Sjkhgt_pch_p_S (void *obj ATTRIBUTE_UNUSED, void *x ATTRIBUTE_UNUSED, 1919Sjkh gt_pointer_operator op ATTRIBUTE_UNUSED, 1929Sjkh void *cookie ATTRIBUTE_UNUSED) 1939Sjkh{ 19450472Speter} 1959Sjkh 1969Sjkh/* PCH pointer-walking routine for strings. */ 19711894Speter 1989Sjkhvoid 19911894Spetergt_pch_n_S (const void *x) 2009Sjkh{ 20111894Speter gt_pch_note_object ((void *)x, (void *)x, >_pch_p_S, 2029Sjkh gt_types_enum_last); 2039Sjkh} 20411894Speter 2059Sjkh/* Handle saving and restoring the string pool for PCH. */ 2069Sjkh 20711894Speter/* SPD is saved in the PCH file and holds the information needed 20811894Speter to restore the string pool. */ 20911894Speter 2109Sjkhstruct string_pool_data GTY(()) 2119Sjkh{ 21211894Speter struct ht_identifier * * 21311894Speter GTY((length ("%h.nslots"), 2149Sjkh nested_ptr (union tree_node, "%h ? GCC_IDENT_TO_HT_IDENT (%h) : NULL", 2159Sjkh "%h ? HT_IDENT_TO_GCC_IDENT (%h) : NULL"))) 2169Sjkh entries; 2179Sjkh unsigned int nslots; 21811894Speter unsigned int nelements; 2199Sjkh}; 2209Sjkh 2219Sjkhstatic GTY(()) struct string_pool_data * spd; 2229Sjkh 2239Sjkh/* Save the stringpool data in SPD. */ 2249Sjkh 2259Sjkhvoid 2269Sjkhgt_pch_save_stringpool (void) 2279Sjkh{ 2289Sjkh spd = ggc_alloc (sizeof (*spd)); 2299Sjkh spd->nslots = ident_hash->nslots; 2309Sjkh spd->nelements = ident_hash->nelements; 2319Sjkh spd->entries = ggc_alloc (sizeof (spd->entries[0]) * spd->nslots); 2329Sjkh memcpy (spd->entries, ident_hash->entries, 2339Sjkh spd->nslots * sizeof (spd->entries[0])); 2349Sjkh} 2359Sjkh 2369Sjkh/* Return the stringpool to its state before gt_pch_save_stringpool 2379Sjkh was called. */ 2389Sjkh 23911894Spetervoid 2409Sjkhgt_pch_fixup_stringpool (void) 2419Sjkh{ 2429Sjkh} 2439Sjkh 2449Sjkh/* A PCH file has been restored, which loaded SPD; fill the real hash table 2459Sjkh from SPD. */ 24611894Speter 2479Sjkhvoid 2489Sjkhgt_pch_restore_stringpool (void) 2499Sjkh{ 2509Sjkh ht_load (ident_hash, spd->entries, spd->nslots, spd->nelements, false); 2519Sjkh spd = NULL; 2529Sjkh} 2539Sjkh 2549Sjkh#include "gt-stringpool.h" 2559Sjkh