public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PCH] read, write memory contents
@ 2002-10-25 23:11 Geoffrey Keating
  0 siblings, 0 replies; only message in thread
From: Geoffrey Keating @ 2002-10-25 23:11 UTC (permalink / raw)
  To: gcc-patches


This patch implements reading and writing of GCed memory to a PCH
file.  It's not quite complete, but nearly all the functionality is
there.

Bootstrapped & tested on powerpc-darwin6.0.

-- 
- Geoffrey Keating <geoffk@apple.com>

===File ~/patches/pchbranch-writeggc-1.patch================
Index: ChangeLog
2002-10-23  Geoffrey Keating  <geoffk@apple.com>

	* gengtype.c (struct write_types_data): New.
	(struct walk_type_data): Make `cookie' const; add extra
	prev_val item; add `orig_s' field.
	(walk_type): Update prev_val[3].
	(write_types_process_field): New.
	(write_func_for_structure): Take write_types_data structure.
	(write_types): New.
	(ggc_wtd): New.
	(pch_wtd): New.
	(write_types_local_process_field): New.
	(gc_mark_process_field): Delete.
	(write_local_func_for_structure): New.
	(gc_mark_func_name): Delete.
	(write_gc_types): Delete.
	(write_local): New.
	(finish_root_table): Don't include 'ggc_' in PFX.
	(write_root): Rename from write_root.  Fill pchw field of structures.
	(write_array): New.
	(write_roots): Rename from write_gc_roots.  Split out to write_array.
	Update to changes to other routines.  Write gt_pch_cache_rtab table.
	(main): Write PCH walking routines.
	* ggc-common.c: Include toplev.h, sys/mman.h.
	(ggc_mark_roots): For cache hashtables, also mark the hash table
	and the array of entries.
	(saving_htab): New.
	(struct ptr_data): New.
	(POINTER_HASH): New.
	(gt_pch_note_object): New.
	(saving_htab_hash): New.
	(saving_htab_eq): New.
	(struct traversal_state): New.
	(call_count): New.
	(call_alloc): New.
	(compare_ptr_data): New.
	(relocate_ptrs): New.
	(write_pch_globals): New.
	(struct mmap_info): New.
	(gt_pch_save): New.
	(gt_pch_restore): New.
	* ggc-page.c (ROUND_UP_VALUE): New.
	(ROUND_UP): New.
	(struct page_entry): Add field `pch_page'.
	(init_ggc): Use ROUND_UP.
	(struct ggc_pch_data): Declare.
	(init_ggc_pch): New.
	(ggc_pch_count_object): New.
	(ggc_pch_total_size): New.
	(ggc_pch_this_base): New.
	(ggc_pch_alloc_object): New.
	(ggc_pch_prepare_write): New.
	(ggc_pch_write_object): New.
	(ggc_pch_finish): New.
	(ggc_pch_read): New.
	* ggc.h (gt_pointer_operator): New.
	(gt_note_pointers): New.
	(gt_pch_note_object): New prototype.
	(gt_pointer_walker): New.
	(struct ggc_root_tab): Use gt_pointer_walker, add `pchw' field.
	(LAST_GGC_ROOT_TAB): Update.
	(gt_pch_cache_rtab): Declare.
	(gt_pch_scalar_rtab): Declare.
	(struct ggc_cache_tab): Use gt_pointer_walker, add `pchw' field.
	(LAST_GGC_CACHE_TAB): Update.
	(gt_pch_save_stringpool): Declare.
	(gt_pch_restore_stringpool): Declare.
	(gt_pch_p_S): Declare.
	(gt_pch_n_S): Declare.
	(struct ggc_pch_data): Forward-declare.
	(init_ggc_pch): Declare.
	(ggc_pch_count_object): Declare.
	(ggc_pch_total_size): Declare.
	(ggc_pch_this_base): Declare.
	(ggc_pch_alloc_object): Declare.
	(ggc_pch_prepare_write): Declare.
	(ggc_pch_write_object): Declare.
	(ggc_pch_finish): Declare.
	(ggc_pch_read): Declare.
	(gt_pch_save): Declare.
	(gt_pch_restore): Declare.
	* fold-const.c (size_int_type_wide): Allocate size_htab using GGC.
	* emit-rtl.c (init_emit_once): Allocate const_int_htab,
	const_double_htab, mem_attrs_htab using GGC.
	* c-pch.c: Include ggc.h.
	(pch_init): Allow reading PCH file back.
	(c_common_write_pch): Call gt_pch_save.
	(c_common_read_pch): Call gt_pch_restore.
	* c-parse.in (init_reswords): Delete now-untrue comment.
	Allocate ridpointers using GGC.
	* c-objc-common.c (c_objc_common_finish_file): Write PCH before
	calling expand_deferred_fns.
	* c-common.h (ridpointers): Mark for GTY machinery.
	* Makefile.in (stringpool.o): Update dependencies.
	(c-pch.o): Update dependencies.
	(ggc-common.o): Update dependencies.
	* stringpool.c: Include gt-stringpool.h.
	(gt_pch_p_S): New.
	(gt_pch_n_S): New.
	(struct string_pool_data): New.
	(spd): New.
	(gt_pch_save_stringpool): New.
	(gt_pch_restore_stringpool): New.
	* tree.c (init_ttree): Make type_hash_table allocated using GC.
	
Index: cp/ChangeLog
2002-10-25  Geoffrey Keating  <geoffk@apple.com>

	* lex.c  (init_reswords): Delete now-untrue comment.
	Allocate ridpointers using GGC.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.822.2.34
diff -u -p -r1.822.2.34 Makefile.in
--- Makefile.in	25 Sep 2002 19:15:39 -0000	1.822.2.34
+++ Makefile.in	24 Oct 2002 04:14:25 -0000
@@ -1249,7 +1249,7 @@ c-semantics.o : c-semantics.c $(CONFIG_H
 c-dump.o : c-dump.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) tree-dump.h
 
 c-pch.o : c-pch.c $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) $(TREE_H) c-common.h \
-	output.h toplev.h c-pragma.h
+	output.h toplev.h c-pragma.h $(GGC_H)
 
 # Language-independent files.
 
@@ -1328,7 +1328,8 @@ gtype-desc.o: gtype-desc.c $(CONFIG_H) $
 	libfuncs.h debug.h $(GGC_H) bitmap.h $(BASIC_BLOCK_H) hard-reg-set.h \
 	ssa.h cselib.h insn-addr.h
 
-ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) $(GGC_H) $(HASHTAB_H)
+ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) $(GGC_H) $(HASHTAB_H) \
+	toplev.h
 
 ggc-simple.o: ggc-simple.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
 	$(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H)
@@ -1337,7 +1338,7 @@ ggc-page.o: ggc-page.c $(CONFIG_H) $(SYS
 	toplev.h $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H)
 
 stringpool.o: stringpool.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(OBSTACK_H) \
-	flags.h toplev.h $(GGC_H)
+	$(GGC_H) gt-stringpool.h
 
 hashtable.o: hashtable.c hashtable.h $(CONFIG_H) $(SYSTEM_H) $(OBSTACK_H)
 
@@ -1850,7 +1851,7 @@ GTFILES = $(GCONFIG_H) \
   $(srcdir)/profile.c $(srcdir)/ra-build.c $(srcdir)/regclass.c \
   $(srcdir)/reg-stack.c \
   $(srcdir)/sdbout.c $(srcdir)/stmt.c $(srcdir)/stor-layout.c \
-  $(srcdir)/tree.c $(srcdir)/varasm.c \
+  $(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \
   $(out_file) \
   @all_gtfiles@
 
@@ -1866,7 +1867,7 @@ gt-alias.h gt-cselib.h gt-fold-const.h g
 gt-expr.h gt-sdbout.h gt-optabs.h gt-bitmap.h gt-dwarf2out.h : s-gtype ; @true
 gt-ra-build.h gt-reg-stack.h gt-dependence.h gt-dwarf2asm.h : s-gtype ; @true
 gt-c-common.h gt-c-decl.h gt-c-parse.h gt-c-pragma.h : s-gtype; @true
-gt-c-objc-common.h gtype-c.h gt-location.h : s-gtype ; @true
+gt-c-objc-common.h gtype-c.h gt-location.h gt-stringpool.h : s-gtype ; @true
 
 gtyp-gen.h: Makefile
 	echo "/* This file is machine generated.  Do not edit.  */" > tmp-gtyp.h
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.112.4.18
diff -u -p -r1.112.4.18 c-common.h
--- c-common.h	25 Sep 2002 19:15:41 -0000	1.112.4.18
+++ c-common.h	24 Oct 2002 04:14:25 -0000
@@ -121,7 +121,7 @@ enum rid
 
 /* The elements of `ridpointers' are identifier nodes for the reserved
    type names and storage classes.  It is indexed by a RID_... value.  */
-extern tree *ridpointers;
+extern GTY ((length ("(int)RID_MAX"))) tree *ridpointers;
 
 /* Standard named or nameless data types of the C compiler.  */
 
Index: c-objc-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-objc-common.c,v
retrieving revision 1.2.6.10
diff -u -p -r1.2.6.10 c-objc-common.c
--- c-objc-common.c	25 Sep 2002 19:15:44 -0000	1.2.6.10
+++ c-objc-common.c	24 Oct 2002 04:14:25 -0000
@@ -1,5 +1,5 @@
 /* Some code common to C and ObjC front ends.
-   Copyright (C) 2001 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -340,10 +340,10 @@ finish_cdtor (body)
 void
 c_objc_common_finish_file ()
 {
-  expand_deferred_fns ();
-
   if (pch_file)
     c_common_write_pch ();
+
+  expand_deferred_fns ();
 
   if (static_ctors)
     {
Index: c-parse.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parse.in,v
retrieving revision 1.125.4.10
diff -u -p -r1.125.4.10 c-parse.in
--- c-parse.in	3 Sep 2002 23:04:49 -0000	1.125.4.10
+++ c-parse.in	24 Oct 2002 04:14:25 -0000
@@ -3554,10 +3554,7 @@ init_reswords ()
   if (!flag_objc)
      mask |= D_OBJC;
 
-  /* It is not necessary to register ridpointers as a GC root, because
-     all the trees it points to are permanently interned in the
-     get_identifier hash anyway.  */
-  ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
+  ridpointers = (tree *) ggc_calloc ((int) RID_MAX, sizeof (tree));
   for (i = 0; i < N_reswords; i++)
     {
       /* If a keyword is disabled, do not enter it into the table
Index: c-pch.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/c-pch.c,v
retrieving revision 1.1.2.3
diff -u -p -r1.1.2.3 c-pch.c
--- c-pch.c	2 Sep 2002 00:35:00 -0000	1.1.2.3
+++ c-pch.c	24 Oct 2002 04:14:25 -0000
@@ -26,6 +26,7 @@ Boston, MA 02111-1307, USA.  */
 #include "output.h"
 #include "toplev.h"
 #include "c-pragma.h"
+#include "ggc.h"
 
 struct c_pch_header 
 {
@@ -46,7 +47,7 @@ pch_init ()
   
   if (pch_file)
     {
-      f = fopen (pch_file, "wb");
+      f = fopen (pch_file, "w+b");
       if (f == NULL)
 	fatal_io_error ("can't open %s", pch_file);
       pch_outfile = f;
@@ -101,6 +102,8 @@ c_common_write_pch ()
     }
   free (buf);
 
+  gt_pch_save (pch_outfile);
+
   fclose (pch_outfile);
 }
 
@@ -200,6 +203,7 @@ c_common_read_pch (pfile, name, fd)
     }
   free (buf);
 
+  gt_pch_restore (f);
+
   fclose (f);
 }
-
Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.242.4.15
diff -u -p -r1.242.4.15 emit-rtl.c
--- emit-rtl.c	25 Sep 2002 19:16:03 -0000	1.242.4.15
+++ emit-rtl.c	24 Oct 2002 04:14:25 -0000
@@ -5314,14 +5314,14 @@ init_emit_once (line_numbers)
 
   /* Initialize the CONST_INT, CONST_DOUBLE, and memory attribute hash
      tables.  */
-  const_int_htab = htab_create (37, const_int_htab_hash,
-				const_int_htab_eq, NULL);
+  const_int_htab = htab_create_ggc (37, const_int_htab_hash,
+				    const_int_htab_eq, NULL);
 
-  const_double_htab = htab_create (37, const_double_htab_hash,
-				   const_double_htab_eq, NULL);
+  const_double_htab = htab_create_ggc (37, const_double_htab_hash,
+				       const_double_htab_eq, NULL);
 
-  mem_attrs_htab = htab_create (37, mem_attrs_htab_hash,
-				mem_attrs_htab_eq, NULL);
+  mem_attrs_htab = htab_create_ggc (37, mem_attrs_htab_hash,
+				    mem_attrs_htab_eq, NULL);
 
   no_line_numbers = ! line_numbers;
 
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.181.4.11
diff -u -p -r1.181.4.11 fold-const.c
--- fold-const.c	25 Sep 2002 19:16:08 -0000	1.181.4.11
+++ fold-const.c	24 Oct 2002 04:14:26 -0000
@@ -1393,7 +1393,7 @@ size_int_type_wide (number, type)
 
   if (size_htab == 0)
     {
-      size_htab = htab_create (1024, size_htab_hash, size_htab_eq, NULL);
+      size_htab = htab_create_ggc (1024, size_htab_hash, size_htab_eq, NULL);
       new_const = make_node (INTEGER_CST);
     }
 
Index: gengtype.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gengtype.c,v
retrieving revision 1.1.2.36
diff -u -p -r1.1.2.36 gengtype.c
--- gengtype.c	5 Oct 2002 02:27:42 -0000	1.1.2.36
+++ gengtype.c	24 Oct 2002 04:14:26 -0000
@@ -1374,44 +1374,63 @@ typedef void (*process_field_fn) 
 typedef void (*func_name_fn)
      PARAMS ((type_p s, const struct walk_type_data *p));
 
+/* Parameters for write_types.  */
+
+struct write_types_data 
+{
+  const char *prefix;
+  const char *param_prefix;
+  const char *subfield_marker_routine;
+  const char *marker_routine;
+  const char *comment;
+};
+
 static void output_escaped_param PARAMS ((struct walk_type_data *d, 
 					  const char *, const char *));
 static void output_mangled_typename PARAMS ((outf_p, type_p));
 static void walk_type PARAMS ((type_p t, struct walk_type_data *d));
-static void write_func_for_structure 
-    PARAMS ((type_p orig_s, type_p s, type_p * param, 
-	     process_field_fn process_field, func_name_fn func_name,
-	     const char *seen_routine, void *cookie));
-static void gc_mark_process_field PARAMS ((type_p f, 
-					   const struct walk_type_data *d));
-static void gc_mark_func_name PARAMS ((type_p f,
-				       const struct walk_type_data *d));
-static void write_gc_types PARAMS ((type_p structures, type_p param_structs));
+static void write_func_for_structure
+     PARAMS ((type_p orig_s, type_p s, type_p * param,
+	      const struct write_types_data *wtd));
+static void write_types_process_field 
+     PARAMS ((type_p f, const struct walk_type_data *d));
+static void write_types PARAMS ((type_p structures, 
+				 type_p param_structs,
+				 const struct write_types_data *wtd));
+static void write_types_local_process_field
+     PARAMS ((type_p f, const struct walk_type_data *d));
+static void write_local_func_for_structure
+     PARAMS ((type_p orig_s, type_p s, type_p * param));
+static void write_local PARAMS ((type_p structures, 
+				 type_p param_structs));
 static void write_enum_defn PARAMS ((type_p structures, type_p param_structs));
 static void put_mangled_filename PARAMS ((outf_p , const char *));
 static void finish_root_table PARAMS ((struct flist *flp, const char *pfx, 
 				       const char *tname, const char *lastname,
 				       const char *name));
-static void write_gc_root PARAMS ((outf_p , pair_p, type_p, const char *, int,
+static void write_root PARAMS ((outf_p , pair_p, type_p, const char *, int,
 				   struct fileloc *, const char *));
-static void write_gc_roots PARAMS ((pair_p));
+static void write_array PARAMS ((outf_p f, pair_p v,
+				 const struct write_types_data *wtd));
+static void write_roots PARAMS ((pair_p));
 
 /* Parameters for walk_type.  */
 
 struct walk_type_data
 {
   process_field_fn process_field;
-  void *cookie;
+  const void *cookie;
   outf_p of;
   options_p opt;
   const char *val;
-  const char *prev_val[3];
+  const char *prev_val[4];
   int indent;
   int counter;
   struct fileloc *line;
   lang_bitmap bitmap;
   type_p *param;
   int used_length;
+  type_p orig_s;
 };
 
 /* Print a mangled name representing T to OF.  */
@@ -1630,6 +1649,7 @@ walk_type (t, d)
 	  {
 	    int loopcounter = d->counter++;
 	    const char *oldval = d->val;
+	    const char *oldprevval3 = d->prev_val[3];
 	    char *newval;
 
 	    oprintf (d->of, "%*sif (%s != NULL) {\n", d->indent, "", d->val);
@@ -1643,9 +1663,11 @@ walk_type (t, d)
 	    d->indent += 2;
 	    d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
 	    d->used_length = 1;
+	    d->prev_val[3] = oldval;
 	    walk_type (t->u.p, d);
 	    free (newval);
 	    d->val = oldval;
+	    d->prev_val[3] = oldprevval3;
 	    d->used_length = 0;
 	    d->indent -= 2;
 	    oprintf (d->of, "%*s}\n", d->indent, "");
@@ -1850,25 +1872,70 @@ walk_type (t, d)
     }
 }
 
+/* process_field routine for marking routines.  */
+
+static void
+write_types_process_field (f, d)
+     type_p f;
+     const struct walk_type_data *d;
+{
+  const struct write_types_data *wtd;
+  wtd = (const struct write_types_data *) d->cookie;
+  
+  switch (f->kind)
+    {
+    case TYPE_POINTER:
+      oprintf (d->of, "%*s%s (%s", d->indent, "", 
+	       wtd->subfield_marker_routine, d->val);
+      if (wtd->param_prefix)
+	{
+	  if (d->orig_s)
+	    {
+	      oprintf (d->of, ", gt_%s_", wtd->param_prefix);
+	      output_mangled_typename (d->of, d->orig_s);
+	    }
+	  else
+	    oprintf (d->of, ", gt_%sa_%s", wtd->param_prefix, d->prev_val[0]);
+	  oprintf (d->of, ", %s", d->prev_val[3]);
+	}
+      oprintf (d->of, ");\n");
+      break;
+
+    case TYPE_STRING:
+      if (wtd->param_prefix == NULL)
+	break;
+
+    case TYPE_STRUCT:
+    case TYPE_UNION:
+    case TYPE_LANG_STRUCT:
+    case TYPE_PARAM_STRUCT:
+      oprintf (d->of, "%*sgt_%s_", d->indent, "", wtd->prefix);
+      output_mangled_typename (d->of, f);
+      oprintf (d->of, " (%s);\n", d->val);
+      break;
+
+    case TYPE_SCALAR:
+      break;
+      
+    default:
+      abort ();
+    }
+}
+
 /* For S, a structure that's part of ORIG_S, and using parameters
    PARAM, write out a routine that:
-   - Is named by the result of FUNC_NAME
    - Takes a parameter, a void * but actually of type *S
-   - If SEEN_ROUTINE returns nonzero, calls PROCESS_FIELD on each
+   - If SEEN_ROUTINE returns nonzero, calls write_types_process_field on each
      field of S or its substructures and (in some cases) things
      that are pointed to by S.
 */
 
 static void
-write_func_for_structure (orig_s, s, param, process_field, func_name,
-			  seen_routine, cookie)
+write_func_for_structure (orig_s, s, param, wtd)
      type_p orig_s;
      type_p s;
      type_p * param;
-     process_field_fn process_field;
-     func_name_fn func_name;
-     const char *seen_routine;
-     void *cookie;
+     const struct write_types_data *wtd;
 {
   const char *fn = s->u.s.line.file;
   int i;
@@ -1895,19 +1962,27 @@ write_func_for_structure (orig_s, s, par
   if (chain_prev != NULL && chain_next == NULL)
     error_at_line (&s->u.s.line, "chain_prev without chain_next");
 
-  d.process_field = process_field;
-  d.cookie = cookie;
+  d.process_field = write_types_process_field;
+  d.cookie = wtd;
+  d.orig_s = orig_s;
   d.opt = s->u.s.opt;
   d.line = &s->u.s.line;
   d.bitmap = s->u.s.bitmap;
   d.param = param;
   d.prev_val[0] = "*x";
   d.prev_val[1] = "not valid postage";  /* guarantee an error */
+  d.prev_val[3] = "x";
   d.val = "(*x)";
 
   oprintf (d.of, "\n");
   oprintf (d.of, "void\n");
-  func_name (orig_s, &d);
+  if (param == NULL)
+    oprintf (d.of, "gt_%sx_%s", wtd->prefix, orig_s->u.s.tag);
+  else
+    {
+      oprintf (d.of, "gt_%s_", wtd->prefix);
+      output_mangled_typename (d.of, orig_s);
+    }
   oprintf (d.of, " (x_p)\n");
   oprintf (d.of, "      void *x_p;\n");
   oprintf (d.of, "{\n");
@@ -1919,10 +1994,26 @@ write_func_for_structure (orig_s, s, par
     oprintf (d.of, "  %s %s * xlimit = x;\n",
 	     s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
   if (chain_next == NULL)
-    oprintf (d.of, "  if (%s (x))\n", seen_routine);
+    {
+      oprintf (d.of, "  if (%s (x", wtd->marker_routine);
+      if (wtd->param_prefix)
+	{
+	  oprintf (d.of, ", gt_%s_", wtd->param_prefix);
+	  output_mangled_typename (d.of, orig_s);
+	  oprintf (d.of, ", x");
+	}
+      oprintf (d.of, "))\n");
+    }
   else
     {
-      oprintf (d.of, "  while (%s (xlimit))\n", seen_routine);
+      oprintf (d.of, "  while (%s (xlimit", wtd->marker_routine);
+      if (wtd->param_prefix)
+	{
+	  oprintf (d.of, ", gt_%s_", wtd->param_prefix);
+	  output_mangled_typename (d.of, orig_s);
+	  oprintf (d.of, ", xlimit");
+	}
+      oprintf (d.of, "))\n");
       oprintf (d.of, "   xlimit = (");
       d.prev_val[2] = "*xlimit";
       output_escaped_param (&d, chain_next, "chain_next");
@@ -1940,7 +2031,15 @@ write_func_for_structure (orig_s, s, par
 	  oprintf (d.of, ");\n");
 	  oprintf (d.of, "        if (xprev == NULL) break;\n");
 	  oprintf (d.of, "        x = xprev;\n");
-	  oprintf (d.of, "        (void) %s (xprev);\n", seen_routine);
+	  oprintf (d.of, "        (void) %s (xprev", 
+		   wtd->marker_routine);
+	  if (wtd->param_prefix)
+	    {
+	      oprintf (d.of, ", gt_%s_", wtd->param_prefix);
+	      output_mangled_typename (d.of, orig_s);
+	      oprintf (d.of, ", xprev");
+	    }
+	  oprintf (d.of, ");\n");
 	  oprintf (d.of, "      }\n");
 	}
       oprintf (d.of, "  while (x != xlimit)\n");
@@ -1962,31 +2061,140 @@ write_func_for_structure (orig_s, s, par
   oprintf (d.of, "}\n");
 }
 
+/* Write out marker routines for STRUCTURES and PARAM_STRUCTS.  */
+
+static void
+write_types (structures, param_structs, wtd)
+     type_p structures;
+     type_p param_structs;
+     const struct write_types_data *wtd;
+{
+  type_p s;
+  
+  oprintf (header_file, "\n/* %s*/\n", wtd->comment);
+  for (s = structures; s; s = s->next)
+    if (s->gc_used == GC_POINTED_TO
+	|| s->gc_used == GC_MAYBE_POINTED_TO)
+      {
+	options_p opt;
+	
+	if (s->gc_used == GC_MAYBE_POINTED_TO
+	    && s->u.s.line.file == NULL)
+	  continue;
+
+	oprintf (header_file, "#define gt_%s_", wtd->prefix);
+	output_mangled_typename (header_file, s);
+	oprintf (header_file, "(X) do { \\\n");
+	oprintf (header_file,
+		 "  if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix, 
+		 s->u.s.tag);
+	oprintf (header_file,
+		 "  } while (0)\n");
+	
+	for (opt = s->u.s.opt; opt; opt = opt->next)
+	  if (strcmp (opt->name, "ptr_alias") == 0)
+	    {
+	      type_p t = (type_p) opt->info;
+	      if (t->kind == TYPE_STRUCT 
+		  || t->kind == TYPE_UNION
+		  || t->kind == TYPE_LANG_STRUCT)
+		oprintf (header_file,
+			 "#define gt_%sx_%s gt_%sx_%s\n",
+			 wtd->prefix, s->u.s.tag, wtd->prefix, t->u.s.tag);
+	      else
+		error_at_line (&s->u.s.line, 
+			       "structure alias is not a structure");
+	      break;
+	    }
+	if (opt)
+	  continue;
+
+	/* Declare the marker procedure only once.  */
+	oprintf (header_file, 
+		 "extern void gt_%sx_%s PARAMS ((void *));\n",
+		 wtd->prefix, s->u.s.tag);
+  
+	if (s->u.s.line.file == NULL)
+	  {
+	    fprintf (stderr, "warning: structure `%s' used but not defined\n", 
+		     s->u.s.tag);
+	    continue;
+	  }
+  
+	if (s->kind == TYPE_LANG_STRUCT)
+	  {
+	    type_p ss;
+	    for (ss = s->u.s.lang_struct; ss; ss = ss->next)
+	      write_func_for_structure (s, ss, NULL, wtd);
+	  }
+	else
+	  write_func_for_structure (s, s, NULL, wtd);
+      }
+
+  for (s = param_structs; s; s = s->next)
+    if (s->gc_used == GC_POINTED_TO)
+      {
+	type_p * param = s->u.param_struct.param;
+	type_p stru = s->u.param_struct.stru;
+
+	/* Declare the marker procedure.  */
+	oprintf (header_file, "extern void gt_%s_", wtd->prefix);
+	output_mangled_typename (header_file, s);
+	oprintf (header_file, " PARAMS ((void *));\n");
+  
+	if (stru->u.s.line.file == NULL)
+	  {
+	    fprintf (stderr, "warning: structure `%s' used but not defined\n", 
+		     s->u.s.tag);
+	    continue;
+	  }
+  
+	if (stru->kind == TYPE_LANG_STRUCT)
+	  {
+	    type_p ss;
+	    for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
+	      write_func_for_structure (s, ss, param, wtd);
+	  }
+	else
+	  write_func_for_structure (s, stru, param, wtd);
+      }
+}
+
+static const struct write_types_data ggc_wtd =
+{
+  "ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark",
+  "GC marker procedures.  "
+};
+
+static const struct write_types_data pch_wtd =
+{
+  "pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object",
+  "PCH type-walking procedures.  "
+};
+
+/* Write out the local pointer-walking routines.  */
 
-/* process_field routine for GC marking.  */
+/* process_field routine for local pointer-walking.  */
 
 static void
-gc_mark_process_field (f, d)
+write_types_local_process_field (f, d)
      type_p f;
      const struct walk_type_data *d;
 {
   switch (f->kind)
     {
     case TYPE_POINTER:
-      oprintf (d->of, "%*sggc_set_mark (%s);\n", d->indent, "", d->val);
-      break;
-
     case TYPE_STRUCT:
     case TYPE_UNION:
     case TYPE_LANG_STRUCT:
     case TYPE_PARAM_STRUCT:
-      oprintf (d->of, "%*sgt_ggc_m_", d->indent, "");
-      output_mangled_typename (d->of, f);
-      oprintf (d->of, " (%s);\n", d->val);
+    case TYPE_STRING:
+      oprintf (d->of, "%*sif ((void *)(%s) == this_obj)\n", d->indent, "",
+	       d->prev_val[3]);
+      oprintf (d->of, "%*s  op (&(%s), cookie);\n", d->indent, "", d->val);
       break;
 
     case TYPE_SCALAR:
-    case TYPE_STRING:
       break;
       
     default:
@@ -1994,50 +2202,78 @@ gc_mark_process_field (f, d)
     }
 }
 
-/* func_name routine for GC marking.  */
+/* For S, a structure that's part of ORIG_S, and using parameters
+   PARAM, write out a routine that:
+   - Is of type gt_note_pointers
+   - If calls PROCESS_FIELD on each field of S or its substructures.
+*/
 
 static void
-gc_mark_func_name (f, d)
-     type_p f;
-     const struct walk_type_data *d;
+write_local_func_for_structure (orig_s, s, param)
+     type_p orig_s;
+     type_p s;
+     type_p * param;
 {
-  if (d->param == NULL)
-    oprintf (d->of, "gt_ggc_mx_%s", f->u.s.tag);
-  else
-    {
-      oprintf (d->of, "gt_ggc_m_");
-      output_mangled_typename (d->of, f);
-    }
+  const char *fn = s->u.s.line.file;
+  int i;
+  struct walk_type_data d;
+  
+  /* This is a hack, and not the good kind either.  */
+  for (i = NUM_PARAM - 1; i >= 0; i--)
+    if (param && param[i] && param[i]->kind == TYPE_POINTER 
+	&& UNION_OR_STRUCT_P (param[i]->u.p))
+      fn = param[i]->u.p->u.s.line.file;
+  
+  memset (&d, 0, sizeof (d));
+  d.of = get_output_file_with_visibility (fn);
+  
+  d.process_field = write_types_local_process_field;
+  d.opt = s->u.s.opt;
+  d.line = &s->u.s.line;
+  d.bitmap = s->u.s.bitmap;
+  d.param = param;
+  d.prev_val[0] = d.prev_val[2] = "*x";
+  d.prev_val[1] = "not valid postage";  /* guarantee an error */
+  d.prev_val[3] = "x";
+  d.val = "(*x)";
+
+  oprintf (d.of, "\n");
+  oprintf (d.of, "void\n");
+  oprintf (d.of, "gt_pch_p_");
+  output_mangled_typename (d.of, orig_s);
+  oprintf (d.of, " (this_obj, x_p, op, cookie)\n");
+  oprintf (d.of, "      void *this_obj ATTRIBUTE_UNUSED;\n");
+  oprintf (d.of, "      void *x_p;\n");
+  oprintf (d.of, "      gt_pointer_operator op ATTRIBUTE_UNUSED;\n");
+  oprintf (d.of, "      void *cookie ATTRIBUTE_UNUSED;\n");
+  oprintf (d.of, "{\n");
+  oprintf (d.of, "  %s %s * const x ATTRIBUTE_UNUSED = (%s %s *)x_p;\n",
+	   s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
+	   s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
+  d.indent = 2;
+  walk_type (s, &d);
+  oprintf (d.of, "}\n");
 }
 
-/* Write out marker routines for STRUCTURES and PARAM_STRUCTS.  */
+/* Write out local marker routines for STRUCTURES and PARAM_STRUCTS.  */
 
 static void
-write_gc_types (structures, param_structs)
+write_local (structures, param_structs)
      type_p structures;
      type_p param_structs;
 {
   type_p s;
   
-  oprintf (header_file, "\n/* GC marker procedures.  */\n");
+  oprintf (header_file, "\n/* Local pointer-walking routines.  */\n");
   for (s = structures; s; s = s->next)
     if (s->gc_used == GC_POINTED_TO
 	|| s->gc_used == GC_MAYBE_POINTED_TO)
       {
 	options_p opt;
 	
-	if (s->gc_used == GC_MAYBE_POINTED_TO
-	    && s->u.s.line.file == NULL)
+	if (s->u.s.line.file == NULL)
 	  continue;
 
-	oprintf (header_file, "#define gt_ggc_m_");
-	output_mangled_typename (header_file, s);
-	oprintf (header_file, "(X) do { \\\n");
-	oprintf (header_file,
-		 "  if (X != NULL) gt_ggc_mx_%s (X);\\\n", s->u.s.tag);
-	oprintf (header_file,
-		 "  } while (0)\n");
-	
 	for (opt = s->u.s.opt; opt; opt = opt->next)
 	  if (strcmp (opt->name, "ptr_alias") == 0)
 	    {
@@ -2045,9 +2281,13 @@ write_gc_types (structures, param_struct
 	      if (t->kind == TYPE_STRUCT 
 		  || t->kind == TYPE_UNION
 		  || t->kind == TYPE_LANG_STRUCT)
-		oprintf (header_file,
-			 "#define gt_ggc_mx_%s gt_ggc_mx_%s\n",
-			 s->u.s.tag, t->u.s.tag);
+		{
+		  oprintf (header_file, "#define gt_pch_p_");
+		  output_mangled_typename (header_file, s);
+		  oprintf (header_file, " gt_pch_p_");
+		  output_mangled_typename (header_file, t);
+		  oprintf (header_file, "\n");
+		}
 	      else
 		error_at_line (&s->u.s.line, 
 			       "structure alias is not a structure");
@@ -2057,29 +2297,19 @@ write_gc_types (structures, param_struct
 	  continue;
 
 	/* Declare the marker procedure only once.  */
+	oprintf (header_file, "extern void gt_pch_p_");
+	output_mangled_typename (header_file, s);
 	oprintf (header_file, 
-		 "extern void gt_ggc_mx_%s PARAMS ((void *));\n",
-		 s->u.s.tag);
-  
-	if (s->u.s.line.file == NULL)
-	  {
-	    fprintf (stderr, "warning: structure `%s' used but not defined\n", 
-		     s->u.s.tag);
-	    continue;
-	  }
+	 "\n    PARAMS ((void *, void *, gt_pointer_operator, void *));\n");
   
 	if (s->kind == TYPE_LANG_STRUCT)
 	  {
 	    type_p ss;
 	    for (ss = s->u.s.lang_struct; ss; ss = ss->next)
-	      write_func_for_structure (s, ss, NULL, gc_mark_process_field,
-					gc_mark_func_name, 
-					"ggc_test_and_set_mark", NULL);
+	      write_local_func_for_structure (s, ss, NULL);
 	  }
 	else
-	  write_func_for_structure (s, s, NULL, gc_mark_process_field,
-				    gc_mark_func_name, 
-				    "ggc_test_and_set_mark", NULL);
+	  write_local_func_for_structure (s, s, NULL);
       }
 
   for (s = param_structs; s; s = s->next)
@@ -2089,9 +2319,10 @@ write_gc_types (structures, param_struct
 	type_p stru = s->u.param_struct.stru;
 
 	/* Declare the marker procedure.  */
-	oprintf (header_file, "extern void gt_ggc_m_");
+	oprintf (header_file, "extern void gt_pch_p_");
 	output_mangled_typename (header_file, s);
-	oprintf (header_file, " PARAMS ((void *));\n");
+	oprintf (header_file, 
+	 "\n    PARAMS ((void *, void *, gt_pointer_operator, void *));\n");
   
 	if (stru->u.s.line.file == NULL)
 	  {
@@ -2104,14 +2335,10 @@ write_gc_types (structures, param_struct
 	  {
 	    type_p ss;
 	    for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
-	      write_func_for_structure (s, ss, param, gc_mark_process_field,
-					gc_mark_func_name, 
-					"ggc_test_and_set_mark", NULL);
+	      write_local_func_for_structure (s, ss, param);
 	  }
 	else
-	  write_func_for_structure (s, stru, param, gc_mark_process_field,
-				    gc_mark_func_name, 
-				    "ggc_test_and_set_mark", NULL);
+	  write_local_func_for_structure (s, stru, param);
       }
 }
 
@@ -2197,7 +2424,7 @@ finish_root_table (flp, pfx, lastname, t
 	  if (bitmap & 1)
 	    {
 	      oprintf (base_files[fnum],
-		       "extern const struct %s gt_ggc_%s_",
+		       "extern const struct %s gt_%s_",
 		       tname, pfx);
 	      put_mangled_filename (base_files[fnum], fli2->name);
 	      oprintf (base_files[fnum], "[];\n");
@@ -2222,7 +2449,7 @@ finish_root_table (flp, pfx, lastname, t
 			   tname, name);
 		  started_bitmap |= 1 << fnum;
 		}
-	      oprintf (base_files[fnum], "  gt_ggc_%s_", pfx);
+	      oprintf (base_files[fnum], "  gt_%s_", pfx);
 	      put_mangled_filename (base_files[fnum], fli2->name);
 	      oprintf (base_files[fnum], ",\n");
 	    }
@@ -2247,7 +2474,7 @@ finish_root_table (flp, pfx, lastname, t
    is nonzero iff we are building the root table for hash table caches.  */
 
 static void
-write_gc_root (f, v, type, name, has_length, line, if_marked)
+write_root (f, v, type, name, has_length, line, if_marked)
      outf_p f;
      pair_p v;
      type_p type;
@@ -2307,8 +2534,8 @@ write_gc_root (f, v, type, name, has_len
 		    char *newname;
 		    newname = xasprintf ("%s.%s.%s", 
 					 name, fld->name, validf->name);
-		    write_gc_root (f, v, validf->type, newname, 0, line,
-				   if_marked);
+		    write_root (f, v, validf->type, newname, 0, line,
+				if_marked);
 		    free (newname);
 		  }
 	      }
@@ -2320,7 +2547,7 @@ write_gc_root (f, v, type, name, has_len
 	      {
 		char *newname;
 		newname = xasprintf ("%s.%s", name, fld->name);
-		write_gc_root (f, v, fld->type, newname, 0, line, if_marked);
+		write_root (f, v, fld->type, newname, 0, line, if_marked);
 		free (newname);
 	      }
 	  }
@@ -2331,7 +2558,7 @@ write_gc_root (f, v, type, name, has_len
       {
 	char *newname;
 	newname = xasprintf ("%s[0]", name);
-	write_gc_root (f, v, type->u.a.p, newname, has_length, line, if_marked);
+	write_root (f, v, type->u.a.p, newname, has_length, line, if_marked);
 	free (newname);
       }
       break;
@@ -2359,17 +2586,21 @@ write_gc_root (f, v, type, name, has_len
 	
 	if (! has_length && UNION_OR_STRUCT_P (tp))
 	  {
-	    oprintf (f, "    &gt_ggc_mx_%s\n", tp->u.s.tag);
+	    oprintf (f, "    &gt_ggc_mx_%s,\n", tp->u.s.tag);
+	    oprintf (f, "    &gt_pch_nx_%s", tp->u.s.tag);
 	  }
 	else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
 	  {
 	    oprintf (f, "    &gt_ggc_m_");
 	    output_mangled_typename (f, tp);
+	    oprintf (f, ",\n    &gt_pch_n_");
+	    output_mangled_typename (f, tp);
 	  }
 	else if (has_length
 		 && (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
 	  {
-	    oprintf (f, "    &gt_ggc_ma_%s", name);
+	    oprintf (f, "    &gt_ggc_ma_%s,\n", name);
+	    oprintf (f, "    &gt_pch_na_%s", name);
 	  }
 	else
 	  {
@@ -2394,10 +2625,62 @@ write_gc_root (f, v, type, name, has_len
     }
 }
 
+/* This generates a routine to walk an array.  */
+
+static void
+write_array (f, v, wtd)
+     outf_p f;
+     pair_p v;
+     const struct write_types_data *wtd;
+{
+  struct walk_type_data d;
+  
+  memset (&d, 0, sizeof (d));
+  d.of = f;
+  d.cookie = wtd;
+  d.indent = 2;
+  d.line = &v->line;
+  d.opt = v->opt;
+  d.bitmap = get_base_file_bitmap (v->line.file);
+  d.param = NULL;
+
+  d.prev_val[3] = xasprintf ("&%s", v->name);
+
+  if (wtd->param_prefix)
+    {
+      oprintf (f, "static void gt_%sa_%s\n", wtd->param_prefix, v->name);
+      oprintf (f, 
+       "    PARAMS ((void *, void *, gt_pointer_operator, void *));\n");
+      oprintf (f, "static void gt_%sa_%s (this_obj, x_p, op, cookie)\n", 
+	       wtd->param_prefix, v->name);
+      oprintf (d.of, "      void *this_obj ATTRIBUTE_UNUSED;\n");
+      oprintf (d.of, "      void *x_p ATTRIBUTE_UNUSED;\n");
+      oprintf (d.of, "      gt_pointer_operator op ATTRIBUTE_UNUSED;\n");
+      oprintf (d.of, "      void *cookie ATTRIBUTE_UNUSED;\n");
+      oprintf (d.of, "{\n");
+      d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
+      d.process_field = write_types_local_process_field;
+      walk_type (v->type, &d);
+      oprintf (f, "}\n\n");
+    }
+
+  oprintf (f, "static void gt_%sa_%s PARAMS ((void *));\n",
+	   wtd->prefix, v->name);
+  oprintf (f, "static void\ngt_%sa_%s (x_p)\n",
+	   wtd->prefix, v->name);
+  oprintf (f, "      void *x_p ATTRIBUTE_UNUSED;\n");
+  oprintf (f, "{\n");
+  d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
+  d.process_field = write_types_process_field;
+  walk_type (v->type, &d);
+  free (d.prev_val[3]);
+  oprintf (f, "}\n\n");
+}
+
 /* Output a table describing the locations and types of VARIABLES.  */
 
 static void
-write_gc_roots (variables)
+write_roots (variables)
      pair_p variables;
 {
   pair_p v;
@@ -2450,26 +2733,8 @@ write_gc_roots (variables)
 	  && (v->type->u.p->kind == TYPE_POINTER
 	      || v->type->u.p->kind == TYPE_STRUCT))
 	{
-	  struct walk_type_data d;
-	  
-	  oprintf (f, "static void gt_ggc_ma_%s PARAMS ((void *));\n",
-		   v->name);
-	  oprintf (f, "static void\ngt_ggc_ma_%s (x_p)\n",
-		   v->name);
-	  oprintf (f, "      void *x_p ATTRIBUTE_UNUSED;\n");
-	  oprintf (f, "{\n");
-	  memset (&d, 0, sizeof (d));
-	  d.of = f;
-	  d.process_field = gc_mark_process_field;
-	  d.prev_val[0] = "*x";
-	  d.prev_val[1] = d.prev_val[2] = d.val = v->name;
-	  d.opt = v->opt;
-	  d.indent = 2;
-	  d.line = &v->line;
-	  d.bitmap = get_base_file_bitmap (v->line.file);
-	  d.param = NULL;
-	  walk_type (v->type, &d);
-	  oprintf (f, "}\n\n");
+	  write_array (f, v, &ggc_wtd);
+	  write_array (f, v, &pch_wtd);
 	}
     }
 
@@ -2503,10 +2768,10 @@ write_gc_roots (variables)
 	  oprintf (f, "[] = {\n");
 	}
 
-      write_gc_root (f, v, v->type, v->name, length_p, &v->line, NULL);
+      write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
     }
 
-  finish_root_table (flp, "r", "LAST_GGC_ROOT_TAB", "ggc_root_tab", 
+  finish_root_table (flp, "ggc_r", "LAST_GGC_ROOT_TAB", "ggc_root_tab", 
 		     "gt_ggc_rtab");
 
   for (v = variables; v; v = v->next)
@@ -2537,11 +2802,11 @@ write_gc_roots (variables)
 	  oprintf (f, "[] = {\n");
 	}
       
-      oprintf (f, "  { &%s, 1, sizeof (%s), NULL },\n",
+      oprintf (f, "  { &%s, 1, sizeof (%s), NULL, NULL },\n",
 	       v->name, v->name);
     }
   
-  finish_root_table (flp, "rd", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+  finish_root_table (flp, "ggc_rd", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
 		     "gt_ggc_deletable_rtab");
 
   for (v = variables; v; v = v->next)
@@ -2581,12 +2846,47 @@ write_gc_roots (variables)
 	  oprintf (f, "[] = {\n");
 	}
       
-      write_gc_root (f, v, v->type->u.p->u.param_struct.param[0],
+      write_root (f, v, v->type->u.p->u.param_struct.param[0],
 		     v->name, length_p, &v->line, if_marked);
     }
   
-  finish_root_table (flp, "rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
+  finish_root_table (flp, "ggc_rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
 		     "gt_ggc_cache_rtab");
+
+  for (v = variables; v; v = v->next)
+    {
+      outf_p f = get_output_file_with_visibility (v->line.file);
+      struct flist *fli;
+      int length_p = 0;
+      int if_marked_p = 0;
+      options_p o;
+      
+      for (o = v->opt; o; o = o->next)
+	if (strcmp (o->name, "length") == 0)
+	  length_p = 1;
+	else if (strcmp (o->name, "if_marked") == 0)
+	  if_marked_p = 1;
+
+      if (! if_marked_p)
+	continue;
+
+      for (fli = flp; fli; fli = fli->next)
+	if (fli->f == f)
+	  break;
+      if (! fli->started_p)
+	{
+	  fli->started_p = 1;
+
+	  oprintf (f, "const struct ggc_root_tab gt_pch_rc_");
+	  put_mangled_filename (f, v->line.file);
+	  oprintf (f, "[] = {\n");
+	}
+
+      write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
+    }
+  
+  finish_root_table (flp, "pch_rc", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+		     "gt_pch_cache_rtab");
 }
 
 \f
@@ -2640,8 +2940,10 @@ main(argc, argv)
 
   open_base_files ();
   write_enum_defn (structures, param_structs);
-  write_gc_types (structures, param_structs);
-  write_gc_roots (variables);
+  write_types (structures, param_structs, &ggc_wtd);
+  write_types (structures, param_structs, &pch_wtd);
+  write_local (structures, param_structs);
+  write_roots (variables);
   write_rtx_next ();
   close_output_files ();
 
Index: ggc-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ggc-common.c,v
retrieving revision 1.46.4.23
diff -u -p -r1.46.4.23 ggc-common.c
--- ggc-common.c	4 Oct 2002 21:09:57 -0000	1.46.4.23
+++ ggc-common.c	24 Oct 2002 04:14:26 -0000
@@ -25,11 +25,26 @@ Software Foundation, 59 Temple Place - S
 #include "system.h"
 #include "hashtab.h"
 #include "ggc.h"
+#include "toplev.h"
+
+#ifdef HAVE_MMAP_FILE
+# include <sys/mman.h>
+#endif
 
 /* Statistics about the allocation.  */
 static ggc_statistics *ggc_stats;
 
+struct traversal_state;
+
 static int ggc_htab_delete PARAMS ((void **, void *));
+static hashval_t saving_htab_hash PARAMS ((const PTR));
+static int saving_htab_eq PARAMS ((const PTR, const PTR));
+static int call_count PARAMS ((void **, void *));
+static int call_alloc PARAMS ((void **, void *));
+static int compare_ptr_data PARAMS ((const void *, const void *));
+static void relocate_ptrs PARAMS ((void *, void *));
+static void write_pch_globals PARAMS ((const struct ggc_root_tab * const *tab,
+				       struct traversal_state *state));
 
 /* Maintain global roots that are preserved during GC.  */
 
@@ -77,7 +92,11 @@ ggc_mark_roots ()
   for (ct = gt_ggc_cache_rtab; *ct; ct++)
     for (cti = *ct; cti->base != NULL; cti++)
       if (*cti->base)
-	htab_traverse (*cti->base, ggc_htab_delete, (PTR) cti);
+	{
+	  ggc_set_mark (*cti->base);
+	  htab_traverse (*cti->base, ggc_htab_delete, (PTR) cti);
+	  ggc_set_mark ((*cti->base)->entries);
+	}
 }
 
 /* Allocate a block of memory, then clear it.  */
@@ -163,4 +182,373 @@ ggc_print_common_statistics (stream, sta
 
   /* Don't gather statistics any more.  */
   ggc_stats = NULL;
+}
+\f
+/* Functions for saving and restoring GCable memory to disk.  */
+
+static htab_t saving_htab;
+
+struct ptr_data 
+{
+  void *obj;
+  gt_note_pointers note_ptr_fn;
+  void *note_ptr_cookie;
+  size_t size;
+  void *new_addr;
+};
+
+#define POINTER_HASH(x) (hashval_t)((long)x >> 3)
+
+/* Register an object in the hash table.  */
+
+int
+gt_pch_note_object (obj, note_ptr_fn, note_ptr_cookie)
+     void *obj;
+     gt_note_pointers note_ptr_fn;
+     void *note_ptr_cookie;
+{
+  struct ptr_data **slot;
+  
+  if (obj == NULL || obj == (void *) 1)
+    return 0;
+
+  slot = (struct ptr_data **)
+    htab_find_slot_with_hash (saving_htab, obj, POINTER_HASH (obj),
+			      INSERT);
+  if (*slot != NULL)
+    {
+      if ((*slot)->note_ptr_fn != note_ptr_fn
+	  || (*slot)->note_ptr_cookie != note_ptr_cookie)
+	abort ();
+      return 0;
+    }
+  
+  *slot = xcalloc (sizeof (struct ptr_data), 1);
+  (*slot)->obj = obj;
+  (*slot)->note_ptr_fn = note_ptr_fn;
+  (*slot)->note_ptr_cookie = note_ptr_cookie;
+  if (note_ptr_fn == gt_pch_p_S)
+    (*slot)->size = strlen (obj) + 1;
+  else
+    (*slot)->size = ggc_get_size (obj);
+  return 1;
+}
+
+/* Hash and equality functions for saving_htab, callbacks for htab_create.  */
+
+static hashval_t
+saving_htab_hash (p)
+     const PTR p;
+{
+  return POINTER_HASH (((struct ptr_data *)p)->obj);
+}
+
+static int
+saving_htab_eq (p1, p2)
+     const PTR p1;
+     const PTR p2;
+{
+  return ((struct ptr_data *)p1)->obj == p2;
+}
+
+/* Handy state for the traversal functions.  */
+
+struct traversal_state 
+{
+  FILE *f;
+  struct ggc_pch_data *d;
+  size_t count;
+  struct ptr_data **ptrs;
+  size_t ptrs_i;
+};
+
+/* Callbacks for htab_traverse.  */
+
+static int
+call_count (slot, state_p)
+     void **slot;
+     void *state_p;
+{
+  struct ptr_data *d = (struct ptr_data *)*slot;
+  struct traversal_state *state = (struct traversal_state *)state_p;
+  
+  ggc_pch_count_object (state->d, d->obj, d->size);
+  state->count++;
+  return 1;
+}
+
+static int
+call_alloc (slot, state_p)
+     void **slot;
+     void *state_p;
+{
+  struct ptr_data *d = (struct ptr_data *)*slot;
+  struct traversal_state *state = (struct traversal_state *)state_p;
+  
+  d->new_addr = ggc_pch_alloc_object (state->d, d->obj, d->size);
+  state->ptrs[state->ptrs_i++] = d;
+  return 1;
+}
+
+/* Callback for qsort.  */
+
+static int
+compare_ptr_data (p1_p, p2_p)
+     const void *p1_p;
+     const void *p2_p;
+{
+  struct ptr_data *p1 = *(struct ptr_data *const *)p1_p;
+  struct ptr_data *p2 = *(struct ptr_data *const *)p2_p;
+  return (((size_t)p1->new_addr > (size_t)p2->new_addr)
+	  - ((size_t)p1->new_addr < (size_t)p2->new_addr));
+}
+
+/* Callbacks for note_ptr_fn.  */
+
+static void
+relocate_ptrs (ptr_p, state_p)
+     void *ptr_p;
+     void *state_p;
+{
+  void **ptr = (void **)ptr_p;
+  struct traversal_state *state ATTRIBUTE_UNUSED 
+    = (struct traversal_state *)state_p;
+  struct ptr_data *result;
+
+  if (*ptr == NULL || *ptr == (void *)1)
+    return;
+  
+  result = htab_find_with_hash (saving_htab, *ptr, POINTER_HASH (*ptr));
+  if (result == NULL)
+    abort ();
+  *ptr = result->new_addr;
+}
+
+/* Write out, after relocation, the pointers in TAB.  */
+static void
+write_pch_globals (tab, state)
+     const struct ggc_root_tab * const *tab;
+     struct traversal_state *state;
+{
+  const struct ggc_root_tab *const *rt;
+  const struct ggc_root_tab *rti;
+  size_t i;
+
+  for (rt = tab; *rt; rt++)
+    for (rti = *rt; rti->base != NULL; rti++)
+      for (i = 0; i < rti->nelt; i++)
+	{
+	  void *ptr = *(void **)((char *)rti->base + rti->stride * i);
+	  struct ptr_data *new_ptr;
+	  if (ptr == NULL || ptr == (void *)1)
+	    {
+	      if (fwrite (&ptr, sizeof (void *), 1, state->f) 
+		  != 1)
+		fatal_io_error ("can't write PCH file");
+	    }
+	  else
+	    {
+	      new_ptr = htab_find_with_hash (saving_htab, ptr, 
+					     POINTER_HASH (ptr));
+	      if (fwrite (&new_ptr->new_addr, sizeof (void *), 1, state->f) 
+		  != 1)
+		fatal_io_error ("can't write PCH file");
+	    }
+	}
+}
+
+/* Hold the information we need to mmap the file back in.  */
+
+struct mmap_info 
+{
+  size_t offset;
+  size_t size;
+  void *preferred_base;
+};
+
+/* Write out the state of the compiler to F.  */
+
+void
+gt_pch_save (f)
+     FILE *f;
+{
+  const struct ggc_root_tab *const *rt;
+  const struct ggc_root_tab *rti;
+  size_t i;
+  struct traversal_state state;
+  char *this_object = NULL;
+  size_t this_object_size = 0;
+  struct mmap_info mmi;
+  size_t page_size = getpagesize();
+
+  gt_pch_save_stringpool ();
+
+  saving_htab = htab_create (50000, saving_htab_hash, saving_htab_eq, free);
+
+  for (rt = gt_ggc_rtab; *rt; rt++)
+    for (rti = *rt; rti->base != NULL; rti++)
+      for (i = 0; i < rti->nelt; i++)
+	(*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
+
+  for (rt = gt_pch_cache_rtab; *rt; rt++)
+    for (rti = *rt; rti->base != NULL; rti++)
+      for (i = 0; i < rti->nelt; i++)
+	(*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
+
+  /* Prepare the objects for writing, determine addresses and such.  */
+  state.f = f;
+  state.d = init_ggc_pch();
+  state.count = 0;
+  htab_traverse (saving_htab, call_count, &state);
+
+  mmi.size = ggc_pch_total_size (state.d);
+
+  /* Try to arrange things so that no relocation is necessary,
+     but don't try very hard.  On most platforms, this will always work,
+     and on the rest it's a lot of work to do better.  */
+#if HAVE_MMAP_FILE
+  mmi.preferred_base = mmap (NULL, mmi.size, 
+			     PROT_READ | PROT_WRITE, MAP_PRIVATE,
+			     fileno (state.f), 0);
+  if (mmi.preferred_base == (void *)-1)
+    mmi.preferred_base = NULL;
+  else
+    munmap (mmi.preferred_base, mmi.size);
+#else /* HAVE_MMAP_FILE */
+  mmi.preferred_base = NULL;
+#endif /* HAVE_MMAP_FILE */
+
+  ggc_pch_this_base (state.d, mmi.preferred_base);
+
+  state.ptrs = xmalloc (state.count * sizeof (*state.ptrs));
+  state.ptrs_i = 0;
+  htab_traverse (saving_htab, call_alloc, &state);
+  qsort (state.ptrs, state.count, sizeof (*state.ptrs), compare_ptr_data);
+
+  /* Write out all the global pointers, after translation.  */
+  write_pch_globals (gt_ggc_rtab, &state);
+  write_pch_globals (gt_pch_cache_rtab, &state);
+
+  ggc_pch_prepare_write (state.d, state.f);
+  
+  /* Pad the PCH file so that the mmaped area starts on a page boundary.  */
+  {
+    off_t o;
+    o = ftello (state.f) + sizeof (mmi);
+    if (o == (off_t) -1)
+      fatal_io_error ("can't get position in PCH file");
+    mmi.offset = page_size - o % page_size;
+    if (mmi.offset == page_size)
+      mmi.offset = 0;
+    mmi.offset += o;
+  }
+  if (fwrite (&mmi, sizeof (mmi), 1, state.f) != 1)
+    fatal_io_error ("can't write PCH file");
+  if (mmi.offset != 0
+      && fseek (state.f, mmi.offset, SEEK_SET) != 0)
+    fatal_io_error ("can't write padding to PCH file");
+
+  /* Actually write out the objects.  */
+  for (i = 0; i < state.count; i++)
+    {
+      if (this_object_size < state.ptrs[i]->size)
+	{
+	  this_object_size = state.ptrs[i]->size;
+	  this_object = xrealloc (this_object, this_object_size);
+	}
+      memcpy (this_object, state.ptrs[i]->obj, state.ptrs[i]->size);
+      state.ptrs[i]->note_ptr_fn (state.ptrs[i]->obj, 
+				  state.ptrs[i]->note_ptr_cookie,
+				  relocate_ptrs, &state);
+      ggc_pch_write_object (state.d, state.f, state.ptrs[i]->obj,
+			    state.ptrs[i]->new_addr, state.ptrs[i]->size);
+      if (state.ptrs[i]->note_ptr_fn != gt_pch_p_S)
+	memcpy (state.ptrs[i]->obj, this_object, state.ptrs[i]->size);
+    }
+  ggc_pch_finish (state.d, state.f);
+
+  free (state.ptrs);
+  htab_delete (saving_htab);
+}
+
+/* Read the state of the compiler back in from F.  */
+
+void
+gt_pch_restore (f)
+     FILE *f;
+{
+  const struct ggc_root_tab *const *rt;
+  const struct ggc_root_tab *rti;
+  size_t i;
+  struct mmap_info mmi;
+  void *addr;
+
+  /* Delete any deletable objects.  This makes ggc_pch_read much
+     faster, as it can be sure that no GCable objects remain other
+     than the ones just read in.  */
+  for (rt = gt_ggc_deletable_rtab; *rt; rt++)
+    for (rti = *rt; rti->base != NULL; rti++)
+      memset (rti->base, 0, rti->stride);
+
+  /* Read in all the global pointers, in 6 easy loops.  */
+  for (rt = gt_ggc_rtab; *rt; rt++)
+    for (rti = *rt; rti->base != NULL; rti++)
+      for (i = 0; i < rti->nelt; i++)
+	if (fread ((char *)rti->base + rti->stride * i,
+		   sizeof (void *), 1, f) != 1)
+	  fatal_io_error ("can't read PCH file");
+
+  for (rt = gt_pch_cache_rtab; *rt; rt++)
+    for (rti = *rt; rti->base != NULL; rti++)
+      for (i = 0; i < rti->nelt; i++)
+	if (fread ((char *)rti->base + rti->stride * i,
+		   sizeof (void *), 1, f) != 1)
+	  fatal_io_error ("can't read PCH file");
+
+  if (fread (&mmi, sizeof (mmi), 1, f) != 1)
+    fatal_io_error ("can't read PCH file");
+  
+#if HAVE_MMAP_FILE
+  addr = mmap (mmi.preferred_base, mmi.size, 
+	       PROT_READ | PROT_WRITE, MAP_PRIVATE,
+	       fileno (f), mmi.offset);
+#else
+  addr = (void *)-1;
+#endif
+  if (addr == (void *)-1)
+    {
+      addr = xmalloc (mmi.size);
+      if (fseek (f, mmi.offset, SEEK_SET) != 0
+	  || fread (&mmi, mmi.size, 1, f) != 1)
+	fatal_io_error ("can't read PCH file");
+    }
+  else if (fseek (f, mmi.offset + mmi.size, SEEK_SET) != 0)
+    fatal_io_error ("can't read PCH file");
+
+  ggc_pch_read (f, addr);
+
+  if (addr != mmi.preferred_base)
+    {
+      for (rt = gt_ggc_rtab; *rt; rt++)
+	for (rti = *rt; rti->base != NULL; rti++)
+	  for (i = 0; i < rti->nelt; i++)
+	    {
+	      char **ptr = (char **)((char *)rti->base + rti->stride * i);
+	      if (*ptr != NULL)
+		*ptr += (size_t)addr - (size_t)mmi.preferred_base;
+	    }
+      
+      for (rt = gt_pch_cache_rtab; *rt; rt++)
+	for (rti = *rt; rti->base != NULL; rti++)
+	  for (i = 0; i < rti->nelt; i++)
+	    {
+	      char **ptr = (char **)((char *)rti->base + rti->stride * i);
+	      if (*ptr != NULL)
+		*ptr += (size_t)addr - (size_t)mmi.preferred_base;
+	    }
+
+      sorry ("had to relocate PCH");
+    }
+
+  gt_pch_restore_stringpool ();
 }
Index: ggc-page.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ggc-page.c,v
retrieving revision 1.48.4.3
diff -u -p -r1.48.4.3 ggc-page.c
--- ggc-page.c	3 Sep 2002 23:05:04 -0000	1.48.4.3
+++ ggc-page.c	24 Oct 2002 04:14:26 -0000
@@ -210,6 +210,15 @@ struct max_alignment {
 
 #define MAX_ALIGNMENT (offsetof (struct max_alignment, u))
 
+/* Compute the smallest nonnegative number which when added to X gives
+   a multiple of F.  */
+
+#define ROUND_UP_VALUE(x, f) ((f) - 1 - ((f) - 1 + (x)) % (f))
+
+/* Compute the smallest multiple of F that is >= X.  */
+
+#define ROUND_UP(x, f) (CEIL (x, f) * (f))
+
 /* The Ith entry is the number of objects on a page or order I.  */
 
 static unsigned objects_per_page_table[NUM_ORDERS];
@@ -266,6 +275,9 @@ typedef struct page_entry
   /* The lg of size of objects allocated from this page.  */
   unsigned char order;
 
+  /* Nonzero if the objects on this page never get freed.  */
+  unsigned char pch_page;
+
   /* A bit vector indicating whether or not objects are in use.  The
      Nth bit is one if the Nth object on this page is allocated.  This
      array is dynamically sized.  */
@@ -1167,7 +1179,7 @@ init_ggc ()
 
       /* If S is not a multiple of the MAX_ALIGNMENT, then round it up
 	 so that we're sure of getting aligned memory.  */
-      s = CEIL (s, MAX_ALIGNMENT) * MAX_ALIGNMENT;
+      s = ROUND_UP (s, MAX_ALIGNMENT);
       object_size_table[order] = s;
     }
 
@@ -1580,4 +1592,193 @@ ggc_print_statistics ()
 	   SCALE (G.bytes_mapped), LABEL (G.bytes_mapped),
 	   SCALE (G.allocated), LABEL(G.allocated),
 	   SCALE (total_overhead), LABEL (total_overhead));
+}
+\f
+struct ggc_pch_data
+{
+  struct ggc_pch_ondisk 
+  {
+    unsigned totals[NUM_ORDERS];
+  } d;
+  size_t base[NUM_ORDERS];
+  size_t written[NUM_ORDERS];
+};
+
+struct ggc_pch_data *
+init_ggc_pch ()
+{
+  return xcalloc (sizeof (struct ggc_pch_data), 1);
+}
+
+void 
+ggc_pch_count_object (d, x, size)
+     struct ggc_pch_data *d;
+     void *x ATTRIBUTE_UNUSED;
+     size_t size;
+{
+  unsigned order;
+
+  if (size <= 256)
+    order = size_lookup[size];
+  else
+    {
+      order = 9;
+      while (size > OBJECT_SIZE (order))
+	order++;
+    }
+  
+  d->d.totals[order]++;
+}
+     
+size_t
+ggc_pch_total_size (d)
+     struct ggc_pch_data *d;
+{
+  size_t a = 0;
+  unsigned i;
+
+  for (i = 0; i < NUM_ORDERS; i++)
+    a += ROUND_UP (d->d.totals[i] * OBJECT_SIZE (i), G.pagesize);
+  return a;
+}
+
+void
+ggc_pch_this_base (d, base)
+     struct ggc_pch_data *d;
+     void *base;
+{
+  size_t a = (size_t) base;
+  unsigned i;
+  
+  for (i = 0; i < NUM_ORDERS; i++)
+    {
+      d->base[i] = a;
+      a += ROUND_UP (d->d.totals[i] * OBJECT_SIZE (i), G.pagesize);
+    }
+}
+
+
+char *
+ggc_pch_alloc_object (d, x, size)
+     struct ggc_pch_data *d;
+     void *x ATTRIBUTE_UNUSED;
+     size_t size;
+{
+  unsigned order;
+  char *result;
+  
+  if (size <= 256)
+    order = size_lookup[size];
+  else
+    {
+      order = 9;
+      while (size > OBJECT_SIZE (order))
+	order++;
+    }
+
+  result = (char *) d->base[order];
+  d->base[order] += OBJECT_SIZE (order);
+  return result;
+}
+
+void 
+ggc_pch_prepare_write (d, f)
+     struct ggc_pch_data * d ATTRIBUTE_UNUSED;
+     FILE * f ATTRIBUTE_UNUSED;
+{
+  /* Nothing to do.  */
+}
+
+void
+ggc_pch_write_object (d, f, x, newx, size)
+     struct ggc_pch_data * d ATTRIBUTE_UNUSED;
+     FILE *f;
+     void *x;
+     void *newx ATTRIBUTE_UNUSED;
+     size_t size;
+{
+  unsigned order;
+
+  if (size <= 256)
+    order = size_lookup[size];
+  else
+    {
+      order = 9;
+      while (size > OBJECT_SIZE (order))
+	order++;
+    }
+  
+  if (fwrite (x, size, 1, f) != 1)
+    fatal_io_error ("can't write PCH file");
+
+  /* In the current implementation, SIZE is always equal to
+     OBJECT_SIZE (order) and so the fseek is never executed.  */
+  if (size != OBJECT_SIZE (order)
+      && fseek (f, OBJECT_SIZE (order) - size, SEEK_CUR) != 0)
+    fatal_io_error ("can't write PCH file");
+
+  d->written[order]++;
+  if (d->written[order] == d->d.totals[order]
+      && fseek (f, ROUND_UP_VALUE (d->d.totals[order] * OBJECT_SIZE (order),
+				   G.pagesize),
+		SEEK_CUR) != 0)
+    fatal_io_error ("can't write PCH file");
+}
+
+void
+ggc_pch_finish (d, f)
+     struct ggc_pch_data * d;
+     FILE *f;
+{
+  if (fwrite (&d->d, sizeof (d->d), 1, f) != 1)
+    fatal_io_error ("can't write PCH file");
+  free (d);
+}
+
+void
+ggc_pch_read (f, addr)
+     FILE *f;
+     void *addr;
+{
+  struct ggc_pch_ondisk d;
+  unsigned i;
+  char *offs = addr;
+  
+  /* We've just read in a PCH file.  So, every object that used to be allocated
+     is now free.  */
+  clear_marks ();
+#ifdef GGC_POISON
+  poison_pages ();
+#endif
+
+  if (fread (&d, sizeof (d), 1, f) != 1)
+    fatal_io_error ("can't read PCH file");
+  
+  for (i = 0; i < NUM_ORDERS; i++)
+    {
+      struct page_entry *entry;
+      char *pte;
+      size_t bmap_size;
+      
+      if (d.totals[i] == 0)
+	continue;
+      
+      bmap_size = BITMAP_SIZE (d.totals[i] + 1);
+      entry = xcalloc (1, (sizeof (struct page_entry) 
+			   - sizeof (long)
+			   + bmap_size));
+      entry->bytes = ROUND_UP (d.totals[i] * OBJECT_SIZE (i), G.pagesize);
+      entry->page = offs;
+      offs += entry->bytes;
+      entry->num_free_objects = 0;
+      entry->order = i;
+      entry->pch_page = 1;
+
+      memset (entry->in_use_p, -1, bmap_size);
+
+      for (pte = entry->page; 
+	   pte < entry->page + entry->bytes; 
+	   pte += G.pagesize)
+	set_page_table_entry (pte, entry);
+    }
 }
Index: ggc.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ggc.h,v
retrieving revision 1.39.6.22
diff -u -p -r1.39.6.22 ggc.h
--- ggc.h	25 Sep 2002 19:16:11 -0000	1.39.6.22
+++ ggc.h	24 Oct 2002 04:14:26 -0000
@@ -18,8 +18,6 @@ along with GCC; see the file COPYING.  I
 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
-#include "gtype-desc.h"
-
 /* Symbols are marked with `ggc' for `gcc gc' so as not to interfere with
    an external gc library that might be linked in.  */
 
@@ -28,21 +26,41 @@ extern const char empty_string[];	/* emp
 extern const char digit_vector[];	/* "0" .. "9" */
 #define digit_string(d) (digit_vector + ((d) * 2))
 
-/* Internal GGC functions and data structures used by the marking
+/* Internal functions and data structures used by the GTY
    machinery.  */
 
+/* The first parameter is a pointer to a pointer, the second a cookie.  */
+typedef void (*gt_pointer_operator) PARAMS ((void *, void *));
+
+#include "gtype-desc.h"
+
+/* One of these applies its third parameter (with cookie in the fourth
+   parameter) to each pointer in the object pointed to by the first
+   parameter, using the second parameter.  */
+typedef void (*gt_note_pointers) 
+     PARAMS ((void *, void *, gt_pointer_operator, void *));
+
+/* Used by the gt_pch_n_* routines.  */
+extern int gt_pch_note_object PARAMS ((void *, gt_note_pointers, void *));
+
+/* Mark the object in the first parameter and anything it points to.  */
+typedef void (*gt_pointer_walker) PARAMS ((void *));
+
 /* Structures for the easy way to mark roots.
    In an array, terminated by having base == NULL.*/
 struct ggc_root_tab {
   void *base;
   size_t nelt;
   size_t stride;
-  void (*cb) PARAMS ((void *));
+  gt_pointer_walker cb;
+  gt_pointer_walker pchw;
 };
-#define LAST_GGC_ROOT_TAB { NULL, 0, 0, NULL }
+#define LAST_GGC_ROOT_TAB { NULL, 0, 0, NULL, NULL }
 /* Pointers to arrays of ggc_root_tab, terminated by NULL.  */
 extern const struct ggc_root_tab * const gt_ggc_rtab[];
 extern const struct ggc_root_tab * const gt_ggc_deletable_rtab[];
+extern const struct ggc_root_tab * const gt_pch_cache_rtab[];
+extern const struct ggc_root_tab * const gt_pch_scalar_rtab[];
 
 /* Structure for hash table cache marking.  */
 struct htab;
@@ -50,10 +68,11 @@ struct ggc_cache_tab {
   struct htab * *base;
   size_t nelt;
   size_t stride;
-  void (*cb) PARAMS ((void *));
+  gt_pointer_walker cb;
+  gt_pointer_walker pchw;
   int (*marked_p) PARAMS ((const void *));
 };
-#define LAST_GGC_CACHE_TAB { NULL, 0, 0, NULL, NULL }
+#define LAST_GGC_CACHE_TAB { NULL, 0, 0, NULL, NULL, NULL }
 /* Pointers to arrays of ggc_cache_tab, terminated by NULL.  */
 extern const struct ggc_cache_tab * const gt_ggc_cache_rtab[];
 
@@ -84,8 +103,22 @@ extern int ggc_marked_p			PARAMS ((const
 /* Mark the entries in the string pool.  */
 extern void ggc_mark_stringpool		PARAMS ((void));
 
+/* Call ggc_set_mark on all the roots.  */
+
 extern void ggc_mark_roots		PARAMS ((void));
 
+/* Save and restore the string pool entries for PCH.  */
+
+extern void gt_pch_save_stringpool	PARAMS ((void));
+extern void gt_pch_restore_stringpool	PARAMS ((void));
+
+/* PCH handling for strings.  */
+
+extern void gt_pch_p_S			PARAMS ((void *, void *,
+						 gt_pointer_operator, void *));
+extern void gt_pch_n_S			PARAMS ((const void *));
+
+
 /* A GC implementation must provide these functions.  */
 
 /* Initialize the garbage collector.  */
@@ -99,6 +132,27 @@ extern void ggc_push_context	PARAMS ((vo
 /* Finish a GC context.  Any uncollected memory in the new context
    will be merged with the old context.  */
 extern void ggc_pop_context 	PARAMS ((void));
+
+struct ggc_pch_data;
+
+extern struct ggc_pch_data *init_ggc_pch PARAMS ((void));
+extern void ggc_pch_count_object	PARAMS ((struct ggc_pch_data *,
+						 void *, size_t));
+extern size_t ggc_pch_total_size	PARAMS ((struct ggc_pch_data *));
+extern void ggc_pch_this_base		PARAMS ((struct ggc_pch_data *,
+						 void *));
+extern char *ggc_pch_alloc_object	PARAMS ((struct ggc_pch_data *,
+						 void *, size_t));
+extern void ggc_pch_prepare_write	PARAMS ((struct ggc_pch_data *,
+						 FILE *));
+extern void ggc_pch_write_object	PARAMS ((struct ggc_pch_data *,
+						 FILE *, void *, void *,
+						 size_t));
+extern void ggc_pch_finish		PARAMS ((struct ggc_pch_data *,
+						 FILE *));
+
+extern void ggc_pch_read		PARAMS ((FILE *, void *));
+
 \f
 /* Allocation.  */
 
@@ -146,6 +200,12 @@ extern void ggc_collect			PARAMS ((void)
 
 /* Return the number of bytes allocated at the indicated address.  */
 extern size_t ggc_get_size		PARAMS ((const void *));
+
+/* Write out all GCed objects to F.  */
+extern void gt_pch_save			PARAMS ((FILE *f));
+
+/* Read objects previously saved with gt_pch_save from F.  */
+extern void gt_pch_restore		PARAMS ((FILE *f));
 \f
 /* Statistics.  */
 
Index: stringpool.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stringpool.c,v
retrieving revision 1.14.6.3
diff -u -p -r1.14.6.3 stringpool.c
--- stringpool.c	9 Aug 2002 20:21:10 -0000	1.14.6.3
+++ stringpool.c	24 Oct 2002 04:14:26 -0000
@@ -1,5 +1,5 @@
 /* String pool for GCC.
-   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -169,3 +169,71 @@ ggc_mark_stringpool ()
 {
   ht_forall (ident_hash, mark_ident, NULL);
 }
+
+/* Pointer-walking routine for strings (not very interesting, since
+   strings don't contain pointers).  */
+
+void
+gt_pch_p_S (obj, x, op, cookie)
+     void *obj ATTRIBUTE_UNUSED;
+     void *x ATTRIBUTE_UNUSED;
+     gt_pointer_operator op ATTRIBUTE_UNUSED;
+     void *cookie ATTRIBUTE_UNUSED;
+{
+}
+
+/* PCH pointer-walking routine for strings.  */
+
+void
+gt_pch_n_S (x)
+     const void *x;
+{
+  gt_pch_note_object ((void *)x, &gt_pch_p_S, (void *)x);
+}
+
+/* Handle saving and restoring the string pool for PCH.  */
+
+struct string_pool_data GTY(())
+{
+  tree * GTY((length ("%h.nslots"))) entries;
+  unsigned int nslots;
+  unsigned int nelements;
+};
+
+static GTY(()) struct string_pool_data * spd;
+
+void
+gt_pch_save_stringpool ()
+{
+  unsigned int i;
+  
+  spd = ggc_alloc (sizeof (*spd));
+  spd->nslots = ident_hash->nslots;
+  spd->nelements = ident_hash->nelements;
+  spd->entries = ggc_alloc (sizeof (tree *) * spd->nslots);
+  for (i = 0; i < spd->nslots; i++)
+    if (ident_hash->entries[i] != NULL)
+      spd->entries[i] = HT_IDENT_TO_GCC_IDENT (ident_hash->entries[i]);
+    else
+      spd->entries[i] = NULL;
+}
+
+void
+gt_pch_restore_stringpool ()
+{
+  unsigned int i;
+  
+  ident_hash->nslots = spd->nslots;
+  ident_hash->nelements = spd->nelements;
+  ident_hash->entries = xrealloc (ident_hash->entries,
+				  sizeof (hashnode) * spd->nslots);
+  for (i = 0; i < spd->nslots; i++)
+    if (spd->entries[i] != NULL)
+      ident_hash->entries[i] = GCC_IDENT_TO_HT_IDENT (spd->entries[i]);
+    else
+      ident_hash->entries[i] = NULL;
+
+  spd = NULL;
+}
+
+#include "gt-stringpool.h"
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.230.2.15
diff -u -p -r1.230.2.15 tree.c
--- tree.c	25 Sep 2002 19:16:29 -0000	1.230.2.15
+++ tree.c	24 Oct 2002 04:14:26 -0000
@@ -134,8 +134,8 @@ void
 init_ttree ()
 {
   /* Initialize the hash table of types.  */
-  type_hash_table = htab_create (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
-				 type_hash_eq, 0);
+  type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
+				     type_hash_eq, 0);
 }
 
 \f
Index: cp/lex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/lex.c,v
retrieving revision 1.262.2.8
diff -u -p -u -p -r1.262.2.8 lex.c
--- cp/lex.c	25 Sep 2002 19:17:43 -0000	1.262.2.8
+++ cp/lex.c	26 Oct 2002 06:09:39 -0000
@@ -564,10 +564,7 @@ init_reswords ()
   int mask = ((flag_no_asm ? D_ASM : 0)
 	      | (flag_no_gnu_keywords ? D_EXT : 0));
 
-  /* It is not necessary to register ridpointers as a GC root, because
-     all the trees it points to are permanently interned in the
-     get_identifier hash anyway.  */
-  ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
+  ridpointers = (tree *) ggc_calloc ((int) RID_MAX, sizeof (tree));
   for (i = 0; i < ARRAY_SIZE (reswords); i++)
     {
       id = get_identifier (reswords[i].word);
============================================================

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-10-26  6:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-10-25 23:11 [PCH] read, write memory contents Geoffrey Keating

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).