This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[boehm-gc] Add type information for GC-allocated objects
- From: "Laurynas Biveinis" <laurynas dot biveinis at gmail dot com>
- To: "Gcc Patch List" <gcc-patches at gcc dot gnu dot org>
- Cc: "Daniel Berlin" <dberlin at dberlin dot org>
- Date: Sun, 13 Aug 2006 18:06:07 +0300
- Subject: [boehm-gc] Add type information for GC-allocated objects
Hi,
This is a first tiny step towards custom marker routines. This patch
adds a footer to every GC-allocated object where its type tag is
stored. I've adopted http://gcc.gnu.org/ml/gcc/2004-01/msg01081.html
patch for this. For sanity check I've converted the single ggc_alloc()
in alias.c to use typed allocation.
Note that Boehm's GC has its own facilities for typed allocation, see
gc_typed.h. I've made a choice not to use them, but rather add my own
flag, because I hope this code might be reused not only for ggc-boehm.
Commited to the boehms-gc branch.
--
Laurynas
Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c (revision 115762)
+++ gcc/gengtype.c (working copy)
@@ -1545,6 +1545,8 @@
use_param_num = oo->name[9] == '\0' ? 0 : oo->name[9] - '0';
else if (strcmp (oo->name, "use_params") == 0)
use_params_p = 1;
+ else if (strcmp (oo->name, "size_not_fixed") == 0)
+ ;
else if (strcmp (oo->name, "desc") == 0)
desc = oo->info;
else if (strcmp (oo->name, "nested_ptr") == 0)
@@ -2436,7 +2438,7 @@
{
type_p s;
- oprintf (header_file, "\n/* Enumeration of types known. */\n");
+ oprintf (header_file, "\n/* Enumeration of known types. */\n");
oprintf (header_file, "enum gt_types_enum {\n");
for (s = structures; s; s = s->next)
if (s->gc_used == GC_POINTED_TO
@@ -2450,6 +2452,7 @@
output_mangled_typename (header_file, s);
oprintf (header_file, ", \n");
}
+
for (s = param_structs; s; s = s->next)
if (s->gc_used == GC_POINTED_TO)
{
@@ -2457,10 +2460,76 @@
output_mangled_typename (header_file, s);
oprintf (header_file, ", \n");
}
+
oprintf (header_file, " gt_types_enum_last\n");
oprintf (header_file, "};\n");
}
+/* Write out a macro for typed allocations for each known struct or union. */
+
+static void
+write_typed_alloc_defns (type_p structures)
+{
+ type_p s;
+ pair_p p;
+
+ oprintf (header_file,
+ "\n/* Typed allocation for known structs and unions. */\n");
+ for (s = structures; s; s = s->next)
+ if (s->gc_used == GC_POINTED_TO
+ || (s->gc_used == GC_MAYBE_POINTED_TO && s->u.s.line.file != NULL))
+ {
+ options_p o;
+ int have_size = 0;
+ const char *type_kind;
+
+ for (o = s->u.s.opt; o; o = o->next)
+ if (strcmp (o->name, "size_not_fixed") == 0)
+ have_size = 1;
+
+ if (s->kind == TYPE_STRUCT)
+ type_kind = "struct ";
+ else if (s->kind == TYPE_UNION)
+ type_kind = "union ";
+ else
+ type_kind = "";
+
+ oprintf (header_file, "#define ggc_alloc_%s(%s) \\\n",
+ s->u.s.tag, (have_size ? "SIZE" : ""));
+ oprintf (header_file, " ggc_alloc_typed(gt_ggc_e_");
+ output_mangled_typename (header_file, s);
+ if (have_size)
+ oprintf (header_file, ", SIZE)\n");
+ else
+ oprintf (header_file, ", sizeof (%s%s))\n",
+ type_kind, s->u.s.tag);
+ }
+
+ oprintf (header_file,
+ "\n/* Typed allocation for known typedefs. */\n");
+ for (p = typedefs; p != NULL; p = p->next)
+ {
+ s = p->type;
+ if (strcmp (p->name, s->u.s.tag) == 0)
+ continue;
+
+ if (s->gc_used == GC_POINTED_TO
+ || (s->gc_used == GC_MAYBE_POINTED_TO && s->u.s.line.file != NULL))
+ {
+ if (s->kind != TYPE_STRUCT
+ && s->kind != TYPE_UNION)
+ continue;
+
+ oprintf (header_file, "#define ggc_alloc_%s(%s) \\\n",
+ p->name, s->kind == TYPE_STRUCT ? "" : "__SIZE");
+ oprintf (header_file, " ggc_alloc_typed(gt_ggc_e_");
+ output_mangled_typename (header_file, s);
+ oprintf (header_file, ", sizeof (%s%s))\n",
+ s->kind == TYPE_STRUCT ? "struct " : "", s->u.s.tag);
+ }
+ }
+}
+
/* Might T contain any non-pointer elements? */
static int
@@ -3083,6 +3152,7 @@
open_base_files ();
write_enum_defn (structures, param_structs);
+ write_typed_alloc_defns (structures);
write_types (structures, param_structs, &ggc_wtd);
write_types (structures, param_structs, &pch_wtd);
write_local (structures, param_structs);
Index: gcc/ggc-boehm.c
===================================================================
--- gcc/ggc-boehm.c (revision 116062)
+++ gcc/ggc-boehm.c (working copy)
@@ -16,17 +16,25 @@
static int ggc_htab_unregister_weak_ptr(void **slot, void *info);
static void ggc_htab_delete_weak_ptr(void ** slot, void * object,
void * info);
+
static size_t get_used_heap_size(void);
static void register_gty_roots(void);
static void gc_warning_filter(char * msg, GC_word arg);
+
+static enum gt_types_enum *get_type_offset(void * block);
+static enum gt_types_enum get_block_type(void * block);
+
static void register_weak_pointers(void);
static void unregister_weak_pointers(void);
static size_t last_allocated = 0;
+static size_t type_overhead = 0;
static ggc_stringpool_roots stringpool_roots;
static GC_warn_proc default_warn_proc;
+#define OBJ_OVERHEAD sizeof(enum gt_types_enum)
+
void
init_ggc (void)
{
@@ -52,7 +60,39 @@
return result;
}
+enum gt_types_enum *
+get_type_offset(void * block)
+{
+ return (enum gt_types_enum *)((char *)block + GC_size(block) - OBJ_OVERHEAD);
+}
+
void *
+ggc_alloc_typed_stat (enum gt_types_enum type, size_t size MEM_STAT_DECL)
+{
+ void * result = NULL;
+
+ size_t actual_obj_size;
+ const size_t obj_plus_info_size = size + OBJ_OVERHEAD;
+ type_overhead += obj_plus_info_size;
+
+ result = GC_malloc (obj_plus_info_size);
+ actual_obj_size = GC_size(result);
+
+ *(get_type_offset(result)) = type;
+
+ /* Verification */
+ gcc_assert (type == get_block_type (result));
+
+ return result;
+}
+
+enum gt_types_enum
+get_block_type(void * block)
+{
+ return *(get_type_offset(block));
+}
+
+void *
ggc_realloc_stat (void *x, size_t size MEM_STAT_DECL)
{
void * result = GC_REALLOC(x, size);
@@ -177,8 +217,9 @@
size_t
ggc_get_size (const void * block)
{
- return GC_size((void *)block); /* Note that GC_size may return a bit larger
- value than originally requested */
+ return GC_size((void *)block) - OBJ_OVERHEAD; /* Note that GC_size may return
+ a bit larger value than
+ originally requested */
}
int
@@ -267,6 +308,9 @@
fprintf (stderr,
"Used bytes in the heap: %lu\n",
(unsigned long)get_used_heap_size());
+ fprintf (stderr,
+ "Local ggc-boehm overhead: %lu\n",
+ (unsigned long)type_overhead);
}
int
Index: gcc/tree.h
===================================================================
--- gcc/tree.h (revision 115762)
+++ gcc/tree.h (working copy)
@@ -3143,7 +3143,8 @@
for various types of node. */
union tree_node GTY ((ptr_alias (union lang_tree_node),
- desc ("tree_node_structure (&%h)")))
+ desc ("tree_node_structure (&%h)"),
+ size_not_fixed ("")))
{
struct tree_common GTY ((tag ("TS_COMMON"))) common;
struct tree_int_cst GTY ((tag ("TS_INT_CST"))) int_cst;
Index: gcc/alias.c
===================================================================
--- gcc/alias.c (revision 115762)
+++ gcc/alias.c (working copy)
@@ -670,7 +670,7 @@
{
/* Create an entry for the SUPERSET, so that we have a place to
attach the SUBSET. */
- superset_entry = ggc_alloc (sizeof (struct alias_set_entry));
+ superset_entry = ggc_alloc_alias_set_entry();
superset_entry->alias_set = superset;
superset_entry->children
= splay_tree_new_ggc (splay_tree_compare_ints);
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h (revision 115762)
+++ gcc/rtl.h (working copy)
@@ -232,7 +232,8 @@
/* RTL expression ("rtx"). */
struct rtx_def GTY((chain_next ("RTX_NEXT (&%h)"),
- chain_prev ("RTX_PREV (&%h)")))
+ chain_prev ("RTX_PREV (&%h)"),
+ size_not_fixed ("")))
{
/* The kind of expression this is. */
ENUM_BITFIELD(rtx_code) code: 16;