* [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, " >_ggc_mx_%s\n", tp->u.s.tag);
+ oprintf (f, " >_ggc_mx_%s,\n", tp->u.s.tag);
+ oprintf (f, " >_pch_nx_%s", tp->u.s.tag);
}
else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
{
oprintf (f, " >_ggc_m_");
output_mangled_typename (f, tp);
+ oprintf (f, ",\n >_pch_n_");
+ output_mangled_typename (f, tp);
}
else if (has_length
&& (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
{
- oprintf (f, " >_ggc_ma_%s", name);
+ oprintf (f, " >_ggc_ma_%s,\n", name);
+ oprintf (f, " >_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, >_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).