This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[incremental] Patch: FYI: garbage collect strings


I'm checking this in on the incremental-compiler branch.

This patch changes gcc so that strings are properly garbage collected.
Without this, the server will slowly leak memory.

This turns out to be reasonably ugly to implement.  There are cases
where a char* field in some object points to a statically allocated
value.  There are also cases where a char* points to the middle of a
GCd object -- say by something like 'o->f = IDENTIFIER_POINTER
(something)'.

So, the marking code for strings has special cases to handle these.
I didn't update the zone collector.


This patch also changes cpp and gcc so that an identifier's characters
are allocated with the identifier, using the struct hack.  This also
required some pretty ugly stuff.

In particular, IDENTIFIER_POINTER now uses a new langhook value to
determine the offset of the string from the start of the identifier
node.

I know that we are trying to get rid of lang hooks.  I think this one
is still ok, though, as it concerns the layout of an object and not,
strictly speaking, the interpretation of the object.  IOW, this should
not adversely affect LTO.

Again, this change is so that we can collect identifiers and their
string data.  I could have just allocated the strings separately, but
that would have wasted a bit more memory (half a word per identifier
on average).

Note that parts of the libcpp patch are technically good for trunk as
well.  libcpp tries to maintain an abstraction about the layout of
identifiers, and I found a few spots in libcpp that violate this.
I'll try to remember to merge this separately in Stage 1.


This temporarily breaks all other front ends -- I didn't update them
to define the new identifier layout macro.  Naturally I will fix this
up before any substantial merge.

Tom

libcpp/ChangeLog:
2007-11-26  Tom Tromey  <tromey@redhat.com>

	* lex.c (lex_identifier): Use CPP_HASHNODE.
	* traditional.c (lex_identifier): Use CPP_HASHNODE.
	* identifiers.c (alloc_node): Use HT_NODE.  Fix types.  Update for
	change to struct ht.
	(_cpp_init_hashtable): Remove cast.
	(struct callback_info): New struct.
	(cpp_ht_proxy): New function.
	(cpp_forall_identifiers): Use cpp_ht_proxy.
	* include/symtab.h (ht_identifier): Put 'str' at the end.  Change
	type for struct hack.
	(struct ht) <alloc_node>: Add size_t argument.
	* include/cpplib.h (CPP_HASHNODE): Redefine.
	(HT_NODE): Likewise.
	(cpp_hashnode): Put 'ident' at the end.
	* Makefile.in (mostlyclean): Add TAGS.
	(TAGS_SOURCES): New variable.
	(TAGS): New target.
	* symtab.c (ht_lookup_with_hash): Copy directly into HT_STR.

gcc/ChangeLog:
2007-11-26  Tom Tromey  <tromey@redhat.com>

	* c-parser.c (check_hunk_binding): Comment out unused variable.
	* langhooks-def.h (LANG_HOOKS_IDENTIFIER_OFFSET): New define.
	(LANG_HOOKS_INITIALIZER): Use it.
	* c-common.h (C_RID_CODE): Rewrote.
	(struct c_common_identifier) <node>: Remove field.
	* var-tracking.c: Include langhooks.h.
	* tree-outof-ssa.c: Include langhooks.h.
	* ggc-page.c (gt_ggc_m_S): New function.
	* stringpool.c: Include langhooks.h.
	(string_stack): Remove.
	(init_stringpool): Update.
	(alloc_node): Add length argument.  Use build_identifier.
	(ggc_alloc_string): Use ggc_alloc.
	(gt_ggc_m_S): Remove.
	* c-pragma.c: Include langhooks.h.
	* ggc.h (gt_ggc_m_S): Change argument type.
	* print-rtl.c: Include langhooks.h.
	* langhooks.h (struct lang_hooks) <identifier_offset>: New field.
	* c-pretty-print.c: Include langhooks.h.
	* c-decl.c (struct lang_identifier) <node>: New field.
	(C_IDENTIFIER_OFFSET_isnt_accurate): New declaration.
	* c-aux-info.c: Include langhooks.h.
	* c-tree.h (C_SIZEOF_STRUCT_LANG_IDENTIFIER): Redefine.
	(C_IDENTIFIER_OFFSET): New define.
	* c-objc-common.h (LANG_HOOKS_IDENTIFIER_OFFSET): New define.
	* toplev.c (struct save_string_list): New struct.
	(struct compilation_job) <strings>: New field.
	(copy_to_vec): Add 'strings' argument.
	(server_callback): Update.
	* tree.h (IDENTIFIER_LENGTH): Redefine.
	(IDENTIFIER_POINTER): Likewise.
	(IDENTIFIER_HASH_VALUE): Likewise.
	(HT_IDENT_TO_GCC_IDENT): Likewise.
	(GCC_IDENT_TO_HT_IDENT): Likewise.
	(struct tree_identifier) <id>: Remove.
	(build_identifier): Declare.
	* tree.c (make_node_stat): Don't allow IDENTIFIER_NODEs.
	(build_identifier): New function.
	* c-lex.c: Include langhooks.h.
	* gengtype.c (write_types_process_field): Arrange to mark
	strings.
	(open_base_files): Include langhooks.h.
	* tree-complex.c: Include langhooks.h.

Index: libcpp/symtab.c
===================================================================
--- libcpp/symtab.c	(revision 127650)
+++ libcpp/symtab.c	(working copy)
@@ -1,5 +1,5 @@
 /* Hash tables.
-   Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2003, 2004, 2007 Free Software Foundation, Inc.
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
@@ -107,6 +107,7 @@
   unsigned int index;
   size_t sizemask;
   hashnode node;
+  unsigned char *chars;
 
   sizemask = table->nslots - 1;
   index = hash & sizemask;
@@ -155,17 +156,17 @@
   if (insert == HT_NO_INSERT)
     return NULL;
 
-  node = (*table->alloc_node) (table);
+  node = (*table->alloc_node) (table, len);
   table->entries[index] = node;
 
   HT_LEN (node) = (unsigned int) len;
   node->hash_value = hash;
-  if (insert == HT_ALLOC)
-    HT_STR (node) = (const unsigned char *) obstack_copy0 (&table->stack,
-                                                           str, len);
-  else
-    HT_STR (node) = str;
 
+  /* It is ok to cast away const here.  */
+  chars = (unsigned char *) HT_STR (node);
+  strncpy ((char *) chars, (char *) str, len);
+  chars[len] = '\0';
+
   if (++table->nelements * 4 >= table->nslots * 3)
     /* Must expand the string table.  */
     ht_expand (table);
Index: libcpp/Makefile.in
===================================================================
--- libcpp/Makefile.in	(revision 127650)
+++ libcpp/Makefile.in	(working copy)
@@ -1,7 +1,7 @@
 # @configure_input@
 # Makefile for libcpp.  Run 'configure' to generate Makefile from Makefile.in
 
-# Copyright (C) 2004 Free Software Foundation, Inc.
+# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
 
 #This file is part of libcpp.
 
@@ -161,7 +161,7 @@
 	done
 
 mostlyclean:
-	-rm -f *.o
+	-rm -f *.o TAGS
 
 clean: mostlyclean
 	-rm -rf makedepend$(EXEEXT) libcpp.a $(srcdir)/autom4te.cache
@@ -239,6 +239,14 @@
 	rm po/$(PACKAGE).pot.tmp
 
 
+TAGS_SOURCES = $(libcpp_a_SOURCES) makedepend.c internal.h ucnid.h \
+    include/line-map.h include/symtab.h include/cpp-id-data.h \
+    include/cpplib.h include/mkdeps.h system.h
+
+TAGS: $(TAGS_SOURCES)
+	cd $(srcdir) && etags $(TAGS_SOURCES)
+
+
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h	(revision 127671)
+++ libcpp/include/cpplib.h	(working copy)
@@ -566,8 +566,9 @@
   BT_COUNTER			/* `__COUNTER__' */
 };
 
-#define CPP_HASHNODE(HNODE)	((cpp_hashnode *) (HNODE))
-#define HT_NODE(NODE)		((ht_identifier *) (NODE))
+#define CPP_HASHNODE(HNODE) \
+  ((cpp_hashnode *) ((char *) (HNODE) - (offsetof (cpp_hashnode, ident))))
+#define HT_NODE(NODE)		(&((NODE)->ident))
 #define NODE_LEN(NODE)		HT_LEN (&(NODE)->ident)
 #define NODE_NAME(NODE)		HT_STR (&(NODE)->ident)
 
@@ -606,7 +607,6 @@
 
 struct cpp_hashnode GTY(())
 {
-  struct ht_identifier ident;
   unsigned int is_directive : 1;
   unsigned int directive_index : 7;	/* If is_directive,
 					   then index into directive table.
@@ -616,6 +616,7 @@
   unsigned char flags;			/* CPP flags.  */
 
   union _cpp_hashnode_value GTY ((desc ("CPP_HASHNODE_VALUE_IDX (%1)"))) value;
+  struct ht_identifier ident;
 };
 
 /* Call this first to get a handle to pass to other functions.
Index: libcpp/include/symtab.h
===================================================================
--- libcpp/include/symtab.h	(revision 127650)
+++ libcpp/include/symtab.h	(working copy)
@@ -1,5 +1,5 @@
 /* Hash tables.
-   Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2003, 2004, 2007 Free Software Foundation, Inc.
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
@@ -26,9 +26,9 @@
 typedef struct ht_identifier ht_identifier;
 struct ht_identifier GTY(())
 {
-  const unsigned char *str;
   unsigned int len;
   unsigned int hash_value;
+  const unsigned char str[1];
 };
 
 #define HT_LEN(NODE) ((NODE)->len)
@@ -47,7 +47,7 @@
 
   hashnode *entries;
   /* Call back, allocate a node.  */
-  hashnode (*alloc_node) (hash_table *);
+  hashnode (*alloc_node) (hash_table *, size_t);
   /* Call back, allocate something that hangs off a node like a cpp_macro.  
      NULL means use the usual allocator.  */
   void * (*alloc_subobject) (size_t);
Index: libcpp/identifiers.c
===================================================================
--- libcpp/identifiers.c	(revision 127650)
+++ libcpp/identifiers.c	(working copy)
@@ -1,6 +1,6 @@
 /* Hash tables for the CPP library.
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2007 Free Software Foundation, Inc.
    Written by Per Bothner, 1994.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -28,18 +28,19 @@
 #include "cpplib.h"
 #include "internal.h"
 
-static cpp_hashnode *alloc_node (hash_table *);
+static hashnode alloc_node (hash_table *, size_t);
 
 /* Return an identifier node for hashtable.c.  Used by cpplib except
    when integrated with the C front ends.  */
-static cpp_hashnode *
-alloc_node (hash_table *table)
+static hashnode
+alloc_node (hash_table *table, size_t len)
 {
   cpp_hashnode *node;
+  size_t length = len + offsetof (cpp_hashnode, ident.str) + 1;
 
-  node = XOBNEW (&table->pfile->hash_ob, cpp_hashnode);
-  memset (node, 0, sizeof (cpp_hashnode));
-  return node;
+  node = (cpp_hashnode *) obstack_alloc (&table->pfile->hash_ob, length);
+  memset (node, 0, length);
+  return HT_NODE (node);
 }
 
 /* Set up the identifier hash table.  Use TABLE if non-null, otherwise
@@ -53,7 +54,7 @@
     {
       pfile->our_hashtable = 1;
       table = ht_create (13);	/* 8K (=2^13) entries.  */
-      table->alloc_node = (hashnode (*) (hash_table *)) alloc_node;
+      table->alloc_node = alloc_node;
 
       _obstack_begin (&pfile->hash_ob, 0, 0,
 		      (void *(*) (long)) xmalloc,
@@ -107,12 +108,31 @@
   return node && node->type == NT_MACRO;
 }
 
+/* Used to pass information from cpp_forall_identifiers through to the
+   user's callback.  */
+struct callback_info
+{
+  /* The user's callback.  */
+  cpp_cb cb;
+  /* The user's data.  */
+  void *v;
+};
+
+/* Handle mismatch between cpp_cb and ht_cb.  */
+static int
+cpp_ht_proxy (struct cpp_reader *reader, hashnode node, const void *ci)
+{
+  struct callback_info *info = (struct callback_info *) ci;
+  return (info->cb) (reader, CPP_HASHNODE (node), info->v);
+}
+
 /* For all nodes in the hashtable, callback CB with parameters PFILE,
    the node, and V.  */
 void
 cpp_forall_identifiers (cpp_reader *pfile, cpp_cb cb, void *v)
 {
-  /* We don't need a proxy since the hash table's identifier comes
-     first in cpp_hashnode.  */
-  ht_forall (pfile->hash_table, (ht_cb) cb, v);
+  struct callback_info info;
+  info.cb = cb;
+  info.v = v;
+  ht_forall (pfile->hash_table, cpp_ht_proxy, &info);
 }
Index: libcpp/traditional.c
===================================================================
--- libcpp/traditional.c	(revision 127650)
+++ libcpp/traditional.c	(working copy)
@@ -253,8 +253,8 @@
 
   CUR (pfile->context) = cur;
   len = out - pfile->out.cur;
-  result = (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->out.cur,
-				       len, HT_ALLOC);
+  result = CPP_HASHNODE (ht_lookup (pfile->hash_table, pfile->out.cur,
+				    len, HT_ALLOC));
   pfile->out.cur = out;
   return result;
 }
Index: libcpp/lex.c
===================================================================
--- libcpp/lex.c	(revision 127650)
+++ libcpp/lex.c	(working copy)
@@ -1,5 +1,5 @@
 /* CPP Library - lexical analysis.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
    Contributed by Per Bothner, 1994-95.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -538,8 +538,8 @@
       len = cur - base;
       hash = HT_HASHFINISH (hash, len);
 
-      result = (cpp_hashnode *)
-	ht_lookup_with_hash (pfile->hash_table, base, len, hash, HT_ALLOC);
+      result = CPP_HASHNODE (ht_lookup_with_hash (pfile->hash_table,
+						  base, len, hash, HT_ALLOC));
     }
 
   /* Rarely, identifiers require diagnostics when lexed.  */
Index: gcc/tree-complex.c
===================================================================
--- gcc/tree-complex.c	(revision 130053)
+++ gcc/tree-complex.c	(working copy)
@@ -31,6 +31,7 @@
 #include "tree-pass.h"
 #include "tree-ssa-propagate.h"
 #include "diagnostic.h"
+#include "langhooks.h"
 
 
 /* For each complex ssa name, a lattice value.  We're interested in finding
Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c	(revision 130053)
+++ gcc/gengtype.c	(working copy)
@@ -1540,7 +1540,7 @@
       "hard-reg-set.h", "basic-block.h", "cselib.h", "insn-addr.h",
       "optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h",
       "tree-flow.h", "reload.h", "cpp-id-data.h", "tree-chrec.h",
-      "cfglayout.h", "except.h", "output.h", "cfgloop.h", NULL
+      "cfglayout.h", "except.h", "output.h", "cfgloop.h", "langhooks.h", NULL
     };
     const char *const *ifp;
     outf_p gtype_desc_c;
@@ -2363,9 +2363,6 @@
       break;
 
     case TYPE_STRING:
-      if (wtd->param_prefix == NULL)
-	break;
-
     case TYPE_STRUCT:
     case TYPE_UNION:
     case TYPE_LANG_STRUCT:
Index: gcc/c-lex.c
===================================================================
--- gcc/c-lex.c	(revision 130053)
+++ gcc/c-lex.c	(working copy)
@@ -41,6 +41,7 @@
 #include "splay-tree.h"
 #include "debug.h"
 #include "target.h"
+#include "langhooks.h"
 
 /* We may keep statistics about how long which files took to compile.  */
 static int header_time, body_time;
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 130053)
+++ gcc/tree.c	(working copy)
@@ -488,6 +488,7 @@
   tree t;
   enum tree_code_class type = TREE_CODE_CLASS (code);
   size_t length = tree_code_size (code);
+  gcc_assert (code != IDENTIFIER_NODE);
 #ifdef GATHER_STATISTICS
   tree_node_kind kind;
 
@@ -1200,6 +1201,27 @@
   return s;
 }
 
+/* Return a new identifier node of the given size.  The caller will
+   fill in the characters.  */
+
+tree
+build_identifier (size_t size)
+{
+  tree s;
+
+#ifdef GATHER_STATISTICS
+  tree_node_counts[(int) id_kind]++;
+  tree_node_sizes[(int) id_kind] += size;
+#endif  
+
+  s = ggc_alloc_tree (size);
+
+  memset (s, 0, size);
+  TREE_SET_CODE (s, IDENTIFIER_NODE);
+
+  return s;
+}
+
 /* Return a newly constructed COMPLEX_CST node whose value is
    specified by the real and imaginary parts REAL and IMAG.
    Both REAL and IMAG should be constant nodes.  TYPE, if specified,
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 130053)
+++ gcc/tree.h	(working copy)
@@ -1461,23 +1461,25 @@
 /* Define fields and accessors for some special-purpose tree nodes.  */
 
 #define IDENTIFIER_LENGTH(NODE) \
-  (IDENTIFIER_NODE_CHECK (NODE)->identifier.id.len)
+  (GCC_IDENT_TO_HT_IDENT (&(IDENTIFIER_NODE_CHECK (NODE)->identifier))->len)
 #define IDENTIFIER_POINTER(NODE) \
-  ((const char *) IDENTIFIER_NODE_CHECK (NODE)->identifier.id.str)
+  ((const char *) (GCC_IDENT_TO_HT_IDENT (&(IDENTIFIER_NODE_CHECK (NODE)->identifier))->str))
 #define IDENTIFIER_HASH_VALUE(NODE) \
-  (IDENTIFIER_NODE_CHECK (NODE)->identifier.id.hash_value)
+  (GCC_IDENT_TO_HT_IDENT (&(IDENTIFIER_NODE_CHECK (NODE)->identifier))->hash_value)
 
 /* Translate a hash table identifier pointer to a tree_identifier
    pointer, and vice versa.  */
 
 #define HT_IDENT_TO_GCC_IDENT(NODE) \
-  ((tree) ((char *) (NODE) - sizeof (struct tree_common)))
-#define GCC_IDENT_TO_HT_IDENT(NODE) (&((struct tree_identifier *) (NODE))->id)
+  ((tree) ((char *) (NODE) - lang_hooks.identifier_offset))
+#define GCC_IDENT_TO_HT_IDENT(NODE) \
+  ((struct ht_identifier *) ((char *) (NODE) + lang_hooks.identifier_offset))
 
 struct tree_identifier GTY(())
 {
   struct tree_common common;
-  struct ht_identifier id;
+  /* Note that every front end's tree_identifier must include an
+     ht_identifier structure at the end.  */
 };
 
 /* In a TREE_LIST node.  */
@@ -3943,6 +3945,7 @@
 extern tree build_complex (tree, tree, tree);
 extern tree build_one_cst (tree);
 extern tree build_string (int, const char *);
+extern tree build_identifier (size_t);
 extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
 #define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO)
 extern tree build_decl_stat (enum tree_code, tree, tree MEM_STAT_DECL);
Index: gcc/toplev.c
===================================================================
--- gcc/toplev.c	(revision 130053)
+++ gcc/toplev.c	(working copy)
@@ -399,17 +399,27 @@
 DEF_VEC_P(cchar_p);
 DEF_VEC_ALLOC_P(cchar_p,gc);
 
+/* This holds various strings so they are not collected while we
+   run.  */
+struct save_string_list GTY (())
+{
+  const char *str;
+  struct save_string_list *next;
+};
+
 /* The current compilation job.  */
 struct compilation_job GTY(())
 {
-  /* The command-line arguments to the compiler.  This is GC allocated
-     so that file names and the like are not deleted after the current
-     job has completed.  */
+  /* The command-line arguments to the compiler.  */
   VEC(cchar_p,gc) *cc1_arguments;
 
   /* The command-line arguments to the assembler.  */
   VEC(cchar_p,gc) *as_arguments;
 
+  /* This holds various strings so they are not collected while we
+     run.  */
+  struct save_string_list *strings;
+
   /* If not null, the executing assembler sub-process.  */
   struct pex_obj * GTY ((skip)) as_process;
 };
@@ -2292,12 +2302,20 @@
 /* Copy an argument vector into a VEC, reallocating all the strings
    via the GC.  */
 static void
-copy_to_vec (VEC (cchar_p, gc) **out, char **args, int *n_args)
+copy_to_vec (VEC (cchar_p, gc) **out, struct save_string_list **strings,
+	     char **args, int *n_args)
 {
   int i;
   *out = NULL;
   for (i = 0; args[i]; ++i)
-    VEC_safe_push (cchar_p, gc, *out, ggc_strdup (args[i]));
+    {
+      const char *str = ggc_strdup (args[i]);
+      struct save_string_list *save = GGC_NEW (struct save_string_list);
+      save->str = str;
+      save->next = *strings;
+      *strings = save;
+      VEC_safe_push (cchar_p, gc, *out, str);
+    }
   VEC_safe_push (cchar_p, gc, *out, NULL);
   if (n_args)
     *n_args = i - 1;
@@ -2321,8 +2339,8 @@
   sorrycount = 0;
 
   job = GGC_CNEW (struct compilation_job);
-  copy_to_vec (&job->as_arguments, as_argv, NULL);
-  copy_to_vec (&job->cc1_arguments, cc1_argv, &n);
+  copy_to_vec (&job->as_arguments, &job->strings, as_argv, NULL);
+  copy_to_vec (&job->cc1_arguments, &job->strings, cc1_argv, &n);
 
   decode_options (n, VEC_address (cchar_p, job->cc1_arguments));
   flag_unit_at_a_time = 1;
Index: gcc/c-objc-common.h
===================================================================
--- gcc/c-objc-common.h	(revision 130053)
+++ gcc/c-objc-common.h	(working copy)
@@ -29,6 +29,8 @@
 
 #undef LANG_HOOKS_IDENTIFIER_SIZE
 #define LANG_HOOKS_IDENTIFIER_SIZE C_SIZEOF_STRUCT_LANG_IDENTIFIER
+#undef LANG_HOOKS_IDENTIFIER_OFFSET
+#define LANG_HOOKS_IDENTIFIER_OFFSET C_IDENTIFIER_OFFSET
 #undef LANG_HOOKS_FINISH
 #define LANG_HOOKS_FINISH c_common_finish
 #undef LANG_HOOKS_INIT_OPTIONS
Index: gcc/c-tree.h
===================================================================
--- gcc/c-tree.h	(revision 130218)
+++ gcc/c-tree.h	(working copy)
@@ -28,8 +28,13 @@
 /* struct lang_identifier is private to c-decl.c, but langhooks.c needs to
    know how big it is.  This is sanity-checked in c-decl.c.  */
 #define C_SIZEOF_STRUCT_LANG_IDENTIFIER \
-  (sizeof (struct c_common_identifier) + 3 * sizeof (void *))
+  (sizeof (struct c_common_identifier) + 3 * sizeof (void *) \
+   + sizeof (struct cpp_hashnode))
 
+#define C_IDENTIFIER_OFFSET \
+  (sizeof (struct c_common_identifier) + 3 * sizeof (void *) \
+   + offsetof (struct cpp_hashnode, ident))
+
 /* Language-specific declaration information.  */
 
 struct lang_decl GTY(())
Index: gcc/c-aux-info.c
===================================================================
--- gcc/c-aux-info.c	(revision 130053)
+++ gcc/c-aux-info.c	(working copy)
@@ -29,6 +29,7 @@
 #include "tree.h"
 #include "c-tree.h"
 #include "toplev.h"
+#include "langhooks.h"
 
 enum formals_style_enum {
   ansi,
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 130218)
+++ gcc/c-decl.c	(working copy)
@@ -241,12 +241,17 @@
   struct c_binding *symbol_binding; /* vars, funcs, constants, typedefs */
   struct c_binding *tag_binding;    /* struct/union/enum tags */
   struct c_binding *label_binding;  /* labels */
+  struct cpp_hashnode node;
 };
 
 /* Validate c-lang.c's assumptions.  */
 extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
 [(sizeof(struct lang_identifier) == C_SIZEOF_STRUCT_LANG_IDENTIFIER) ? 1 : -1];
 
+extern char C_IDENTIFIER_OFFSET_isnt_accurate
+[(offsetof(struct lang_identifier, node.ident) == C_IDENTIFIER_OFFSET) ? 1 : -1];
+
+
 /* The resulting tree type.  */
 
 union lang_tree_node
Index: gcc/c-pretty-print.c
===================================================================
--- gcc/c-pretty-print.c	(revision 130053)
+++ gcc/c-pretty-print.c	(working copy)
@@ -28,6 +28,7 @@
 #include "c-tree.h"
 #include "tree-iterator.h"
 #include "diagnostic.h"
+#include "langhooks.h"
 
 /* The pretty-printer code is primarily designed to closely follow
    (GNU) C and C++ grammars.  That is to be contrasted with spaghetti
Index: gcc/langhooks.h
===================================================================
--- gcc/langhooks.h	(revision 130053)
+++ gcc/langhooks.h	(working copy)
@@ -222,6 +222,9 @@
      identifier nodes long enough for the language-specific slots.  */
   size_t identifier_size;
 
+  /* Offset of the ht_identifier sub-structure in a lang_identifier.  */
+  size_t identifier_offset;
+
   /* Determines the size of any language-specific tcc_constant or
      tcc_exceptional nodes.  Since it is called from make_node, the
      only information available is the tree code.  Expected to die
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c	(revision 130053)
+++ gcc/print-rtl.c	(working copy)
@@ -40,6 +40,7 @@
 #include "flags.h"
 #include "hard-reg-set.h"
 #include "basic-block.h"
+#include "langhooks.h"
 #endif
 
 static FILE *outfile;
Index: gcc/ggc.h
===================================================================
--- gcc/ggc.h	(revision 130053)
+++ gcc/ggc.h	(working copy)
@@ -162,7 +162,7 @@
 
 extern void gt_pch_p_S (void *, void *, gt_pointer_operator, void *);
 extern void gt_pch_n_S (const void *);
-extern void gt_ggc_m_S (void *);
+extern void gt_ggc_m_S (const void *);
 
 /* Initialize the string pool.  */
 extern void init_stringpool (void);
Index: gcc/c-pragma.c
===================================================================
--- gcc/c-pragma.c	(revision 130125)
+++ gcc/c-pragma.c	(working copy)
@@ -37,6 +37,7 @@
 #include "target.h"
 #include "diagnostic.h"
 #include "opts.h"
+#include "langhooks.h"
 
 #define GCC_BAD(gmsgid) \
   do { warning (OPT_Wpragmas, gmsgid); return; } while (0)
Index: gcc/stringpool.c
===================================================================
--- gcc/stringpool.c	(revision 130053)
+++ gcc/stringpool.c	(working copy)
@@ -35,6 +35,7 @@
 #include "tree.h"
 #include "symtab.h"
 #include "cpplib.h"
+#include "langhooks.h"
 
 /* The "" allocated string.  */
 const char empty_string[] = "";
@@ -47,9 +48,8 @@
 };
 
 struct ht *ident_hash;
-static struct obstack string_stack;
 
-static hashnode alloc_node (hash_table *);
+static hashnode alloc_node (hash_table *, size_t);
 static int mark_ident (struct cpp_reader *, hashnode, const void *);
 
 static void *
@@ -66,14 +66,16 @@
   ident_hash = ht_create (14);
   ident_hash->alloc_node = alloc_node;
   ident_hash->alloc_subobject = stringpool_ggc_alloc;
-  gcc_obstack_init (&string_stack);
 }
 
 /* Allocate a hash node.  */
 static hashnode
-alloc_node (hash_table *table ATTRIBUTE_UNUSED)
+alloc_node (hash_table *table ATTRIBUTE_UNUSED, size_t length)
 {
-  return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE));
+  /* identifier_size includes 1 byte for the string, so we don't need
+     to add one for the \0.  */
+  size_t size = lang_hooks.identifier_size + length;
+  return GCC_IDENT_TO_HT_IDENT (build_identifier (size));
 }
 
 /* Allocate and return a string constant of length LENGTH, containing
@@ -85,6 +87,8 @@
 const char *
 ggc_alloc_string (const char *contents, int length)
 {
+  char *result;
+
   if (length == -1)
     length = strlen (contents);
 
@@ -93,8 +97,9 @@
   if (length == 1 && ISDIGIT (contents[0]))
     return digit_string (contents[0] - '0');
 
-  obstack_grow0 (&string_stack, contents, length);
-  return XOBFINISH (&string_stack, const char *);
+  result = ggc_alloc (length + 1);
+  memcpy (result, contents, length + 1);
+  return (const char *) result;
 }
 
 /* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string).
@@ -173,15 +178,6 @@
   ht_forall (ident_hash, mark_ident, NULL);
 }
 
-/* Strings are _not_ GCed, but this routine exists so that a separate
-   roots table isn't needed for the few global variables that refer
-   to strings.  */
-
-void
-gt_ggc_m_S (void *x ATTRIBUTE_UNUSED)
-{
-}
-
 /* Pointer-walking routine for strings (not very interesting, since
    strings don't contain pointers).  */
 
Index: gcc/ggc-page.c
===================================================================
--- gcc/ggc-page.c	(revision 130053)
+++ gcc/ggc-page.c	(working copy)
@@ -1271,6 +1271,43 @@
   return result;
 }
 
+void
+gt_ggc_m_S (const void *p)
+{
+  page_entry *entry;
+  unsigned bit, word;
+  unsigned long mask;
+
+  if (!p || !ggc_allocated_p (p))
+    return;
+
+  /* Look up the page on which the object is alloced.  .  */
+  entry = lookup_page_table_entry (p);
+  gcc_assert (entry);
+
+  /* Calculate the index of the object on the page; this is its bit
+     position in the in_use_p bitmap.  Note that because a char* might
+     point to the middle of an object, we need special code here to
+     make sure P points to the start of an object.  */
+  p -= ((const char *) p - entry->page) % object_size_table[entry->order];
+  bit = OFFSET_TO_BIT (((const char *) p) - entry->page, entry->order);
+  word = bit / HOST_BITS_PER_LONG;
+  mask = (unsigned long) 1 << (bit % HOST_BITS_PER_LONG);
+
+  /* If the bit was previously set, skip it.  */
+  if (entry->in_use_p[word] & mask)
+    return;
+
+  /* Otherwise set it, and decrement the free object count.  */
+  entry->in_use_p[word] |= mask;
+  entry->num_free_objects -= 1;
+
+  if (GGC_DEBUG_LEVEL >= 4)
+    fprintf (G.debug_file, "Marking %p\n", p);
+
+  return;
+}
+
 /* If P is not marked, marks it and return false.  Otherwise return true.
    P must have been allocated by the GC allocator; it mustn't point to
    static objects, stack variables, or memory allocated with malloc.  */
Index: gcc/tree-outof-ssa.c
===================================================================
--- gcc/tree-outof-ssa.c	(revision 130053)
+++ gcc/tree-outof-ssa.c	(working copy)
@@ -33,6 +33,7 @@
 #include "tree-ssa-live.h"
 #include "tree-pass.h"
 #include "toplev.h"
+#include "langhooks.h"
 
 
 /* Used to hold all the components required to do SSA PHI elimination.
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c	(revision 130053)
+++ gcc/var-tracking.c	(working copy)
@@ -105,6 +105,7 @@
 #include "expr.h"
 #include "timevar.h"
 #include "tree-pass.h"
+#include "langhooks.h"
 
 /* Type of micro operation.  */
 enum micro_operation_type
Index: gcc/c-common.h
===================================================================
--- gcc/c-common.h	(revision 130053)
+++ gcc/c-common.h	(working copy)
@@ -180,14 +180,16 @@
     CTI_MAX
 };
 
-#define C_RID_CODE(id)	(((struct c_common_identifier *) (id))->node.rid_code)
+#define C_RID_CODE(id) \
+  ((CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (id)))->rid_code)
 
 /* Identifier part common to the C front ends.  Inherits from
    tree_identifier, despite appearances.  */
 struct c_common_identifier GTY(())
 {
   struct tree_common common;
-  struct cpp_hashnode node;
+  /* Any C-based FE has to have a cpp_hashnode in here, at the very
+     end.  */
 };
 
 #define wchar_type_node			c_global_trees[CTI_WCHAR_TYPE]
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c	(revision 130218)
+++ gcc/c-parser.c	(working copy)
@@ -895,9 +895,7 @@
   /* We might be using something declared in the current hunk -- don't
      register that fact.  Otherwise, record the name/value pair in our
      prerequisite list.  When evaluating prerequisites we look to make
-     sure that all listed names have the indicated value.  FIXME: we
-     also need to handle NULL values properly, since we may do a
-     "failing" lookup.  */
+     sure that all listed names have the indicated value.  */
   if (!result || (binding && binding != parser->current_hunk_binding))
     {
       htab_t prereqs = parser->current_hunk_binding->prereqs;
@@ -1932,7 +1930,7 @@
 {
   struct hunk_binding *binding = (struct hunk_binding *) *valp;
   struct can_reuse_hunk_data *info = (struct can_reuse_hunk_data *) crhd;
-  c_parser *parser = info->parser;
+/*   c_parser *parser = info->parser; */
   struct parsed_hunk *hunk = info->hunk;
   struct parsed_hunk *binding_iter, *self_iter;
   bool ok;
Index: gcc/langhooks-def.h
===================================================================
--- gcc/langhooks-def.h	(revision 130053)
+++ gcc/langhooks-def.h	(working copy)
@@ -83,6 +83,7 @@
 
 #define LANG_HOOKS_NAME			"GNU unknown"
 #define LANG_HOOKS_IDENTIFIER_SIZE	sizeof (struct lang_identifier)
+#define LANG_HOOKS_IDENTIFIER_OFFSET    offsetof (struct lang_identifier, id)
 #define LANG_HOOKS_INIT			hook_bool_void_false
 #define LANG_HOOKS_FINISH		lhd_do_nothing
 #define LANG_HOOKS_PARSE_FILE		lhd_do_nothing_i
@@ -240,6 +241,7 @@
 #define LANG_HOOKS_INITIALIZER { \
   LANG_HOOKS_NAME, \
   LANG_HOOKS_IDENTIFIER_SIZE, \
+  LANG_HOOKS_IDENTIFIER_OFFSET, \
   LANG_HOOKS_TREE_SIZE, \
   LANG_HOOKS_INIT_OPTIONS, \
   LANG_HOOKS_INITIALIZE_DIAGNOSTICS, \


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]